比赛 HAOI 2018 Day1 评测结果 AAAAAAAA
题目名称 奇怪的背包 最终得分 100
用户昵称 ZRQ 运行时间 0.101 s
代码语言 C++ 内存使用 4.34 MiB
提交时间 2022-04-11 11:54:54
显示代码纯文本
#include<iostream>
#include<cstdio>
#include<cmath> 
using namespace std;
const int N=1000005,M=10005,mod=1e9+7;
int n,q,P,v[N],w[N],p[M],tot,ct[M],f[2][M],sum[N],ans[M];
char ch;
inline void read(int &x){x=0;ch=getchar();while(ch<48||ch>57)ch=getchar();while(ch>47&&ch<58)x=(x<<3)+(x<<1)+(ch^48),ch=getchar();}
inline int gcd(int m,int n)
{
	int t;
	while(n) t=m%n,m=n,n=t;
	return m;
}
int main()
{
	freopen("knapsack.in","r",stdin);
	freopen("knapsack.out","w",stdout);
	int now=0,k;
	read(n),read(q),read(P);
	for(int i=1;i<=n;++i)
		read(v[i]),v[i]=gcd(v[i],P);
	sum[1]=2;
	for(int i=2;i<=n;++i) sum[i]=sum[i-1]*2%mod;//预处理2的幂 
	for(int i=1;i<=n;++i) sum[i]=(sum[i]+mod-1)%mod;
	for(int i=1;i<=sqrt(P);++i)//求P的质因子并保持有序 
		if(P%i==0)
			p[++tot]=i;
	for(int i=tot;i>1;--i)
		if(P/p[i]!=p[i])
			p[++tot]=P/p[i];
	for(int i=1;i<=n;++i)
	{
		int pos=lower_bound(p+1,p+tot+1,v[i])-p;
		++ct[pos];
	}
	for(int i=1;i<=tot;++i)
		if(ct[i])
		{
			now^=1;
			for(int j=1;j<=tot;++j) f[now][j]=f[now^1][j];
			for(int j=1;j<=tot;++j)
				if(f[now^1][j])
				{
					int npos=lower_bound(p+1,p+tot+1,gcd(p[i],p[j]))-p;
					f[now][npos]+=1LL*f[now^1][j]*sum[ct[i]]%mod;
					f[now][npos]%=mod; 
				}
			f[now][i]+=sum[ct[i]]%mod;
			f[now][i]%=mod;
		}
	for(int i=1;i<=tot;++i)
		for(int j=1;j<=i;++j)
			if(p[i]%p[j]==0)
				ans[i]+=f[now][j],ans[i]%=mod;
	for(int i=1;i<=q;++i)
	{
		read(k);
		k=gcd(k,P);
		int pos=lower_bound(p+1,p+tot+1,k)-p;
		printf("%d\n",ans[pos]);
	 } 
	return 0;
}