HDU 3944 DP? [Lucas定理 詭異的預處理]


DP?

Time Limit: 10000/3000 MS (Java/Others)    Memory Limit: 128000/128000 K (Java/Others)
Total Submission(s): 3126    Accepted Submission(s): 978

Problem Description
Input
Input to the problem will consists of series of up to 100000 data sets. For each data there is a line contains three integers n, k(0<=k<=n<10^9) p(p<10^4 and p is a prime) . Input is terminated by end-of-file.
 

數據范圍詭異系列~
題意:楊輝三角可以往左或者往右走走到$(n,k)$的最小權值和

顯然每一層都要取一個權值,並且越往外權值越小,當然是盡量往外最好啦
對稱,k>n/2時變成n-k
如果從$(n,k)$向左斜着上去,結果就是
${n\choose k}+{n-1\choose k-1}+...+{n-k\choose 0}+n-k$
然后用組合數遞推式合並,就是
${n+1\choose k}+n-k$
 
問題在於T太大啦,以致於<10000的質數遠比T小,我們預處理模所有質數意義下的階乘吧!
#include <iostream>
#include
<cstdio>
#include
<cstring>
#include
<algorithm>
#include
<cmath>
using namespace std;
const int N=10007;
int n,m,P;
bool notp[N];
int p[N];
void sieve(int n){
for(int i=2;i<=n;i++){
if(!notp[i]) p[++p[0]]=i;
for(int j=1;j<=p[0]&&i*p[j]<=n;j++){
notp[i
*p[j]]=1;
if(i%p[j]==0) break;
}
}
}
int fac[N][1300],mp[N],pnum;
void ini(int n){
sieve(n);
for(int j=1;j<=p[0];j++){
int x=p[j];mp[x]=j;
fac[
0][j]=1;
for(int i=1;i<=n;i++) fac[i][j]=fac[i-1][j]*i%x;
}
}
int Pow(int a,int b){
int re=1;
for(;b;b>>=1,a=a*a%P)
if(b&1) re=re*a%P;
return re;
}
int Inv(int a){return Pow(a,P-2);}
int C(int n,int m){
if(n<m) return 0;
return fac[n][pnum]*Inv(fac[m][pnum])%P*Inv(fac[n-m][pnum])%P;
}
int Lucas(int n,int m){
if(n<m) return 0;
int re=1;
for(;m;n/=P,m/=P) re=re*C(n%P,m%P)%P;
return re;
}
int main(){
freopen(
"in","r",stdin);
int cas=0;
ini(
10000);
while(scanf("%d%d%d",&n,&m,&P)!=EOF){
if(m>n/2) m=n-m;
pnum
=mp[P];
printf(
"Case #%d: %d\n",++cas,(Lucas(n+1,m)+n-m)%P);
}
}

 

 
 
 
 
 
 

注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
粤ICP备14056181号  © 2014-2020 ITdaan.com