T1 bzoj 1951 古代猪文
题目大意:
给正整数n G 求(G^sigma{C(n,n/i),i|n})%P
思路:
数论题大合集.jpg
设res=sigma{C(n,n/i),i|n 由于res可能很大
由费马小定理可得 我们只需要求res%(P-1)
快速求C需要lucas 因为P-1不是质数 所以还需要使用中国剩余定理合并
最后再快速幂即可
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<cstdlib> 5 #include<cmath> 6 #include<algorithm> 7 #include<queue> 8 #include<vector> 9 #include<map> 10 #define inf 2139062143 11 #define ll long long 12 #define MAXN 40100 13 #define MOD 999911659 14 using namespace std; 15 inline int read() 16 { 17 int x=0,f=1;char ch=getchar(); 18 while(!isdigit(ch)) {if(ch=='-')f=-1;ch=getchar();} 19 while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();} 20 return x*f; 21 } 22 int n,inv[4][MAXN],m[4]={2,3,4679,35617}; 23 ll g[4][MAXN],bas,ans[4]; 24 inline void mem() 25 { 26 for(int k=0;k<4;k++) 27 { 28 inv[k][0]=inv[k][1]=g[k][0]=g[k][1]=1; 29 for(int i=2;i<m[k];i++) inv[k][i]=(m[k]-m[k]/i)*inv[k][m[k]%i]%m[k],g[k][i]=(g[k][i-1]*i)%m[k]; 30 for(int i=2;i<m[k];i++) (inv[k][i]*=inv[k][i-1])%=m[k]; 31 //cout<<k<<" "<<ans[0]<<" "<<ans[1]<<" "<<ans[2]<<" "<<ans[3]<<endl; 32 //cout<<inv[k][2]<<endl; 33 } 34 //cout<<ans[0]<<" "<<ans[1]<<" "<<ans[2]<<" "<<ans[3]<<endl; 35 } 36 inline ll C(ll n,ll x,int k) 37 { 38 //cout<<"C: "<<n<<" "<<x<<" "<<k<<" "<<g[k][n]<<" "<<inv[k][x]<<" "<<inv[k][n-x]<<endl; 39 if(n<x) return 0LL; 40 return (g[k][n]*inv[k][x]*inv[k][n-x])%m[k]; 41 } 42 ll lucas(ll n,ll x,int k) 43 { 44 //cout<<"L: "<<n<<" "<<x<<" "<<k<<" "<<g[k][n]<<" "<<inv[k][x]<<" "<<inv[k][n-x]<<endl; 45 if(!x) return 1LL; 46 return (lucas(n/m[k],x/m[k],k)*C(n%m[k],x%m[k],k))%m[k]; 47 //return *C(n%m[x],x%m[x],k))%m[x]; 48 } 49 inline void work(int x) 50 { 51 for(int i=0;i<4;i++){ 52 //cout<<x<<" "<<i<<" "<<ans[0]<<" "<<ans[1]<<" "<<ans[2]<<" "<<ans[3]<<endl; 53 (ans[i]+=lucas(n,x,i))%=m[i]; 54 } 55 //cout<<x<<" "<<ans[0]<<" "<<ans[1]<<" "<<ans[2]<<" "<<ans[3]<<endl; 56 } 57 inline ll exgcd(ll a,ll b,ll &x,ll &y) 58 { 59 if(!b) {x=1,y=0;return a;} 60 ll d=exgcd(b,a%b,y,x);y-=(a/b)*x;return d; 61 } 62 inline ll q_pow(ll t) 63 { 64 //cout<<t<<endl; 65 ll res=1; 66 for(;t;t>>=1,(bas*=bas)%=MOD) 67 { 68 //cout<<t<<" "<<res<<" "<<bas<<endl; 69 if(t&1) (res*=bas)%=MOD; 70 } 71 return (res+MOD)%MOD; 72 } 73 int main() 74 { 75 n=read(),bas=read();mem(); 76 if(bas==MOD) {puts("0");return 0;} 77 for(int i=1;i*i<=n;i++) 78 if(n%i==0) {work(i);if(i*i!=n) work(n/i);} 79 ll x,y,s=MOD-1,res=0; 80 for(int i=0;i<4;i++) 81 { 82 exgcd(m[i],s/m[i],x,y); 83 (res+=y*s/m[i]*ans[i])%=s; 84 //cout<<y*s/m[i]*ans[i]<<endl; 85 } 86 printf("%lld",q_pow((res+s)%s)); 87 }
T2 bzoj 3398 牡牛和牝牛
题目大意:
N只牛 这些牛公母任意 牛们要站成一排,任意两头公牛之间至少有k头母牛
求有多少种排队方案(所有公牛可看做一样 母牛可看做一样)
思路:
dp i 表示前i头的方案 注意dp 1 =2(公母都可以取)
当这一头为母牛时 dp i+=dp i-1
为公牛时 dp i += dp i-k-1 当i<=k+1时 dp i++
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<cstdlib> 5 #include<cmath> 6 #include<algorithm> 7 #include<queue> 8 #include<vector> 9 #include<map> 10 #define inf 2139062143 11 #define ll long long 12 #define MAXN 100100 13 #define MOD 5000011 14 using namespace std; 15 inline int read() 16 { 17 int x=0,f=1;char ch=getchar(); 18 while(!isdigit(ch)) {if(ch=='-')f=-1;ch=getchar();} 19 while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();} 20 return x*f; 21 } 22 int n,dp[MAXN],k; 23 int main() 24 { 25 n=read(),k=read(),dp[1]=2; 26 for(int i=2;i<=n;i++) 27 if(i<=k+1) dp[i]=dp[i-1]+1; 28 else (dp[i]=dp[i-1]+dp[i-k-1])%=MOD; 29 printf("%d ",dp[n]); 30 }
T3 luogu 1771 方程的解
题目大意:
正整数 k x 求不定方程a1+a2+...+ak=g(x) g(x)=x^x(mod 1000)的正整数解组数
思路:
先快速幂求出g(x) 然后相当于插板 g(x)-1个位置插k-1个板 高精度组合数即可
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<cstdlib> 5 #include<cmath> 6 #include<algorithm> 7 #include<queue> 8 #include<vector> 9 #include<map> 10 #define inf 2139062143 11 #define ll long long 12 #define MAXN 100100 13 using namespace std; 14 inline int read() 15 { 16 int x=0,f=1;char ch=getchar(); 17 while(!isdigit(ch)) {if(ch=='-')f=-1;ch=getchar();} 18 while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();} 19 return x*f; 20 } 21 int n,m,MOD=1000; 22 int q_pow(int t,int p) 23 { 24 int res=1; 25 for(;p;p>>=1,(t*=t)%=MOD) 26 if(p&1) (res*=t)%=MOD; 27 return res; 28 } 29 struct bign 30 { 31 int num[30],len; 32 bign(){memset(num,0,sizeof(num));len=0;} 33 void print() 34 { 35 printf("%d",num[len]); 36 for(int i=len-1;i>=0;i--) printf("%09d",num[i]); 37 } 38 bign operator + (const bign a) const 39 { 40 bign res;res.len=max(len,a.len); 41 for(int i=0;i<=res.len;i++) 42 res.num[i]+=num[i]+a.num[i], 43 res.num[i+1]=res.num[i]/MOD,res.num[i]%=MOD; 44 if(res.num[res.len+1]) res.len++; 45 return res; 46 } 47 }c[1010][1010]; 48 int main() 49 { 50 n=read()-1,m=read(),m=q_pow(m%MOD,m)-1,MOD=1e9; 51 c[0][0].num[0]=1; 52 for(int i=1;i<=m;i++) 53 { 54 c[i][0].num[0]=1; 55 for(int j=1;j<=n&&j<=i;j++) c[i][j]=c[i-1][j]+c[i-1][j-1]; 56 } 57 c[m][n].print(); 58 }
T4 loj 10232 车的放置
题目大意:
形如这样的棋盘 求放k个互不攻击的车(jv) 的方案数
思路:
太菜了不会组合数 选择dp i j 表示前i行放了j个棋子的方案数
可以从i-1 行放了j 个棋子 与 前i-1行放了j-1个转移 后者需要乘这次的方案数
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<cstdlib> 5 #include<cmath> 6 #include<algorithm> 7 #include<queue> 8 #include<vector> 9 #include<map> 10 #define inf 2139062143 11 #define ll long long 12 #define MAXN 5010 13 #define MOD 100003 14 using namespace std; 15 inline int read() 16 { 17 int x=0,f=1;char ch=getchar(); 18 while(!isdigit(ch)) {if(ch=='-')f=-1;ch=getchar();} 19 while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();} 20 return x*f; 21 } 22 int a,b,c,d,k,f[MAXN][MAXN],v[MAXN]; 23 int main() 24 { 25 a=read(),b=read(),c=read(),d=read(),k=read(); 26 for(int i=0;i<=b+d;i++) f[i][0]=1; 27 for(int i=1;i<=b+d;i++) 28 for(int j=1;j<=k&&j<=i;j++) 29 if(i<=b) f[i][j]=(f[i-1][j]+f[i-1][j-1]*(a-j+1))%MOD; 30 else f[i][j]=(f[i-1][j]+f[i-1][j-1]*(a+c-j+1))%MOD; 31 printf("%d",f[b+d][k]); 32 }
T5 bzoj 3505 数三角形
题目大意:
给定一个nxm的网格,请计算三点都在格点上的三角形共有多少个(三点不共线)
思路:
先算出选三个点的方案数再减去共线的方案数
枚举每个三点共线构成线段的这个向量
对于每个向量的方案为可以平移到的位置即(n-i)*(m-j)再乘线段上选点的方案数即gcd(i,j)-1
因为i j为正整数即假设这个线段一端为网格左下角 而左上角的方案相同因此每个向量方案再乘二
但i j 其中一个等于0时不需要乘2因为平移时已经算过了
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<cstdlib> 5 #include<cmath> 6 #include<algorithm> 7 #include<queue> 8 #include<vector> 9 #include<map> 10 #define inf 2139062143 11 #define ll long long 12 #define MAXN 5010 13 #define MOD 100003 14 using namespace std; 15 inline int read() 16 { 17 int x=0,f=1;char ch=getchar(); 18 while(!isdigit(ch)) {if(ch=='-')f=-1;ch=getchar();} 19 while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();} 20 return x*f; 21 } 22 ll n,m,ans; 23 int gcd(int a,int b) {if(!a) return b;return !b?a:gcd(b,a%b);} 24 int main() 25 { 26 n=read()+1,m=read()+1,ans=n*m*(n*m-1)*(n*m-2)/6; 27 for(ll i=0;i<=n;i++) 28 for(ll j=0;j<=m;j++) 29 if(i+j) ans-= ((i*j)?2LL:1LL)*(gcd(i,j)-1LL)*(n-i)*(m-j); 30 printf("%lld",ans); 31 }