3.20省选练习(上午)
$T1$
尽管善意的出题人在题目上写了反演
但是和反演没什么关系吧,可以显然的发现,每个因数是可以单独计算的
那么对于每个因子分开扫一遍就好了,大概是一个类似单调队列的东西,复杂度期望能过
显然上面是错的,因为这样的话是累和,我们的$gcd$是一堆数相乘
那么还是考虑枚举$gcd,$主要是我一开始看成子串了...
那么这个时候就可以显然的计算$dp[i]$的长度了,答案就是$\sum_{l=1}^{n}l\times i\times C(dp[i],l)$
这个$dp$转移首先把所有可能的情况全都组合出来
枚举倍数$sum+=dp[x](i|x)$
#include <bits/stdc++.h> #define mod 1000000007 #define int long long #define MAXN 1000005 int n,cnt[MAXN],fac[MAXN],dp[MAXN],Ans; signed main() { scanf("%lld",&n); for(int i=fac[0]=1;i<=n;i++) { fac[i]=2ll*fac[i-1]%mod; } for(int i=1,x;i<=n;++i) { scanf("%lld",&x); ++cnt[x]; } for(int i=MAXN-1,cur;i>1;i--) { cur=0; for(int j=i;j<MAXN;j+=i) { cur+=cnt[j]; } //我们记得反正是总长度 //那么就把所有情况都计算了 //又由于每种情况都有一个gcd,那么把不满足的减去就好了 if(!cur) continue; dp[i]=fac[cur-1]*cur%mod; for(int j=i+i;j<MAXN;j+=i) { dp[i]=(dp[i]-dp[j]+mod)%mod; } Ans=(Ans+dp[i]*i%mod)%mod; } printf("%d\n",Ans); return 0; }
$T2$
$x^a+y^b=z^c(\mod M)$
给定$a,b,c$
大概给了你幂,让你求底数使得相等
构造的话很有意思,大概构造成这种形式$2^{kab}+2^{kab}=2^{kab+1}$
显然可以构造出一组解,那就好了
#include<bits/stdc++.h> #define ll long long using namespace std; ll a,b,c,T,mod,l,k,x,y,z; void exgcd(ll a0,ll b0,ll &x,ll &y) { if(b0==0) { x=1; y=0; return; } exgcd(b0,a0%b0,y,x); y-=(a0/b0)*x; } ll my_pow(ll x,ll y){ ll res=1; while(y) { if(y&1) { res=(res*x)%mod; } x=(x*x)%mod; y>>=1; } return res%mod; } int main(){ scanf("%lld",&T); while(T--) { scanf("%lld",&mod); scanf("%lld%lld%lld",&a,&b,&c); l=0,k=0; exgcd(c,a*b,l,k); k=-k; if(k<0) { ll p=(-k)/c+1; k=k+c*p; l=l+p*a*b; } else if(k>0) { ll p=k/c; k-=p*c; l-=p*a*b; } x=my_pow(2,k*b); y=my_pow(2,k*a); z=my_pow(2,l); if(x==0||y==0||z==0) { if(a>1) { x=mod/2; y=1;z=1; } else if(b>1) { y=mod/2; x=1;z=1; } else if(c>1) { x=y=z=mod/2; } else { x=1,y=1,z=2; } } printf("%lld %lld %lld\n",x,y,z); } }
$T3$
大概是个组合数$?$
推出来了式子$Ans=\sum_{k=0}^{n}C(m,k)C(m-k,2\times(n-k))Num_k$
现在我们选出了哪些列选的方案数,那么我们就需要对于这种方案求出多少种行的方案数
大概就是我们现在每行有两个颜色相同的球,然后放到不同盒子(容量不同的方案数)
递推加容斥,枚举多少个盒子里面有两个相同颜色的球
$S_k=\frac{1}{2^{n+k}}\sum_{i=0}^{k}(^k_i)(^n_i)i!(-1)^i2^i(2n-2i)!$
那么直接求就好了
#include<bits/stdc++.h> #define MAXN 4000005 #define mod 998244353 #define int long long using namespace std; const int G=3,Ginv=(mod+1)/3; int n,m,ans; int rev[MAXN],jc[MAXN],inv[MAXN],S[MAXN],A[MAXN]; int my_pow(int a,int b) { int res=1; while(b) { if(b&1) { res=(res*a)%mod; } a=(a*a)%mod; b>>=1; } return res; } void NTT(int *A,int lim,int opt) { for(int i=0;i<lim;++i) { rev[i]=(rev[i>>1]>>1)|(i&1?(lim>>1):0); } for(int i=0;i<lim;++i) { if(i<rev[i]) { swap(A[i],A[rev[i]]); } } int len; int wn,w,x,y; for(int mid=1;mid<lim;mid<<=1) { len=mid<<1; wn=my_pow(opt==1?G:Ginv,(mod-1)/len); for(int j=0;j<lim;j+=len) { w=1; for(int k=j;k<j+mid;++k,w=w*wn%mod) { x=A[k];y=A[k+mid]*w%mod; A[k]=(x+y)%mod;A[k+mid]=(x-y+mod)%mod; } } } if(opt==1)return; int ni=my_pow(lim,mod-2); for(int i=0;i<lim;++i)A[i]=A[i]*ni%mod; } void MUL(int *A,int n,int *B,int m) { int lim=1; while(lim<=(n+m))lim<<=1; NTT(A,lim,1);NTT(B,lim,1); for(int i=0;i<lim;++i)A[i]=A[i]*B[i]%mod; NTT(A,lim,-1); } void init(int Maxn) { jc[0]=jc[1]=1; inv[0]=inv[1]=1; for(int i=1;i<=Maxn;++i) { jc[i]=jc[i-1]*i%mod; } inv[Maxn]=my_pow(jc[Maxn],mod-2); for(int i=Maxn-1;i>=1;--i) { inv[i]=inv[i+1]*(i+1)%mod; } } int C(int n,int m) { if(n<m)return 0; return jc[n]*inv[m]%mod*inv[n-m]%mod; } signed main() { // freopen("c.in","r",stdin); // freopen("c.out","w",stdout); cin>>n>>m; init(2*max(n,m)); for(int i=0;i<=n;++i) { S[i]=inv[i]; A[i]=(i&1?-1:1)*my_pow(2,i)*jc[2*n-2*i]%mod*inv[n-i]%mod*inv[i]%mod; } MUL(S,n,A,n); for(int i=0;i<=n;++i) { (ans+=C(m,i)*C(m-i,2*(n-i))%mod*my_pow(2,(n+i)*(mod-2))%mod*jc[i]%mod*jc[n]%mod*S[i])%=mod; } cout<<(ans%mod+mod)%mod; return 0; }