比赛 |
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;
}