比赛 2022级数学专题练习赛8 评测结果 AAAAAAAAAA
题目名称 奇怪的背包 最终得分 100
用户昵称 yrtiop 运行时间 1.278 s
代码语言 C++ 内存使用 5.17 MiB
提交时间 2023-02-06 20:27:06
显示代码纯文本
#include <bits/stdc++.h>
#define pb emplace_back
using i64 = long long;

const int mod = 1e9 + 7;
const int maxm = 1505;
const int maxn = 1e6 + 5;
int n,a[maxn],w[maxn],m,Q,p,cnt[maxm],pw[maxn],f[2][maxm],g[maxm],num[maxm];
std::unordered_map<int,int> s;
std::vector<int> G;

int gcd(int x,int y) {
	return y ? gcd(y , x % y) : x;
}

int add(int x,int y) {
	return (x + y) >= mod ? (x + y - mod) : (x + y);
}

int main() {
	freopen("knapsack.in","r",stdin);
	freopen("knapsack.out","w",stdout);
	scanf("%d %d %d",&n,&Q,&p);
	pw[0] = 1;
	for(int i = 1;i <= n;++ i)
		pw[i] = 2ll * pw[i - 1] % mod;
	for(int i = 0;i <= n;++ i)
		pw[i] = add(pw[i] , mod - 1);
	for(int i = 1;i <= n;++ i)
		scanf("%d",&a[i]),++ s[gcd(a[i] , p)];
	for(int i = 1;i <= Q;++ i)
		scanf("%d",&w[i]);
	for(int i = 1;i * i <= p;++ i)
		if(!(p % i))
			num[++ m] = i;
	for(int i = m;i > 1;-- i)
		if(num[i] * num[i] != p)
			num[++ m] = p / num[i];
	for(int i = 1;i <= m;++ i)
		cnt[i] = s[num[i]];
	bool cur = false;
	for(int i = 1;i <= m;++ i) {
		if(!cnt[i])
			continue ;
		cur ^= true;
		for(int j = 1;j <= m;++ j)
			f[cur][j] = f[cur ^ true][j];
		for(int j = 1;j <= m;++ j) {
			if(!f[cur ^ true][j])
				continue ;
			int t = gcd(num[i] , num[j]);
			int pos = std::lower_bound(num + 1 , num + 1 + m , t) - num;
			f[cur][pos] = add(f[cur][pos] , 1ll * f[cur ^ true][j] * pw[cnt[i]] % mod);
		}
		f[cur][i] = add(f[cur][i] , pw[cnt[i]]);
	}
	for(int i = 1;i <= m;++ i)
		for(int j = 1;j <= i;++ j)
			if(!(num[i] % num[j]))
				g[i] = add(g[i] , f[cur][j]);
	for(int i = 1;i <= Q;++ i) {
		int t = gcd(w[i] , p);
		int pos = std::lower_bound(num + 1 , num + m + 1 , t) - num;
		printf("%d\n",g[pos]);
	}
	return 0;
}