zoukankan      html  css  js  c++  java
  • BZOJ 5302: [Haoi2018]奇怪的背包

    首先根据裴蜀定理,v[i]等价于gcd(v[i],P),w[i]等价于gcd(w[i],P),所以我们只要求出P的约数的答案,F[i][j]表示用了前i种约数,能产生最小值为第j种约数的方案数,统计答案即可

    #include<cstdio>
    #include<algorithm>
    #include<map>
    using namespace std;
    const int mod=1e9+7;
    int n,q,P,top,vec[1000005],ans[1000005],Sum[1000005],V[1000005],F[2005][2005];
    map<int,int> M;
    int gcd(int a,int b){
    	if (b==0) return a;
    	return gcd(b,a%b);
    }
    int main(){
    	scanf("%d%d%d",&n,&q,&P);
    	for (int i=1; i*i<=P; i++)
    		if (P%i==0){
    			vec[++top]=i;
    			M[i]=top;
    			if (i*i!=P) {
    				vec[++top]=P/i;
    				M[P/i]=top;
    			}
    		}
    	for (int i=1; i<=top; i++) Sum[i]=1;
    	for (int i=1; i<=n; i++) {
    		scanf("%d",&V[i]);
    		V[i]=gcd(V[i],P);
    		(Sum[M[V[i]]]<<=1)%=mod; 
    	}
    	F[0][M[P]]=1;
    	for (int i=0; i<top; i++)
    		for (int j=1; j<=top; j++){
    			int x=M[gcd(vec[i+1],vec[j])];
    			(F[i+1][j]+=F[i][j])%=mod;
    			(F[i+1][x]+=1ll*F[i][j]*(Sum[i+1]-1)%mod)%=mod;
    		}
    	for (int i=1; i<=top; i++)
    		for (int j=1; j<=top; j++)
    			if (vec[i]%vec[j]==0) (ans[i]+=F[top][j])%=mod;
    	while (q--){
    		int x;
    		scanf("%d",&x);
    		x=gcd(x,P);
    		int ANS=ans[M[x]];
    		if (x==P) ANS--;
    		(ANS+=mod)%=mod;
    		printf("%d
    ",ANS);
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    ObjectiveC分类
    显示时间格式
    js模拟签名
    安装卸载homebrew
    NSFastEnumeration
    拼接音频
    在Orchard模块中访问模块本地的AppSettings
    重装证书
    msysgit中文问题
    Apple Push Notification service
  • 原文地址:https://www.cnblogs.com/silenty/p/9788397.html
Copyright © 2011-2022 走看看