【LOJ2523】【BZOJ5302】【HAOI2018】奇怪的背包
裴蜀定理+容斥即可。
首先考虑经典的裴蜀定理:有整数解当且仅当。
注意本题并不需要非负的条件,因为可以用来调整。
于是问题就变成了求
首先和显然都可以先和取。
然后设为的约数个数,根据vfk的blog,当时有。
那么我们考虑先对于每个求出
显然这就是,其中
暴力即可。
之后我们暴力容斥求得
然后再统计答案即可。
时间复杂度。
#include <bits/stdc++.h>using namespace std;typedef long long ll;const int MAXSIZE=20000020;const int mod=1000000007;int bufpos;char buf[MAXSIZE];#define NEG 0void init(){#ifdef LOCALfreopen("2532.txt","r",stdin);#endifbuf[fread(buf,1,MAXSIZE,stdin)]='\0';bufpos=0;}#if NEGint readint(){bool isneg;int val=0;for(;!isdigit(buf[bufpos]) && buf[bufpos]!='-';bufpos++);bufpos+=(isneg=buf[bufpos]=='-');for(;isdigit(buf[bufpos]);bufpos++)val=val*10+buf[bufpos]-'0';return isneg?-val:val;}#elseint readint(){int val=0;for(;!isdigit(buf[bufpos]);bufpos++);for(;isdigit(buf[bufpos]);bufpos++)val=val*10+buf[bufpos]-'0';return val;}#endifchar readchar(){for(;isspace(buf[bufpos]);bufpos++);return buf[bufpos++];}int readstr(char* s){int cur=0;for(;isspace(buf[bufpos]);bufpos++);for(;!isspace(buf[bufpos]);bufpos++)s[cur++]=buf[bufpos];s[cur]='\0';return cur;}int d[2002];ll cnt[2002];int pw[1000002];int main(){init();int n=readint(),q=readint(),p=readint(),cur=0;for(int i=1;i*i<=p;i++)if (p%i==0){d[++cur]=i;if (i*i!=p)d[++cur]=p/i;}sort(d+1,d+cur+1);pw[0]=1;for(int i=1;i<=n;i++){pw[i]=pw[i-1]*2;if (pw[i]>=mod)pw[i]-=mod;}while(n--)cnt[lower_bound(d+1,d+cur+1,__gcd(readint(),p))-d]++;for(int i=1;i<=cur;i++)for(int j=i+1;j<=cur;j++)if (d[j]%d[i]==0)cnt[i]+=cnt[j];for(int i=1;i<=cur;i++)cnt[i]=pw[cnt[i]]-1;for(int i=cur;i;i--){for(int j=i+1;j<=cur;j++)if (d[j]%d[i]==0)cnt[i]-=cnt[j];cnt[i]%=mod;}for(int i=cur;i;i--){for(int j=1;j<i;j++)if (d[i]%d[j]==0)cnt[i]+=cnt[j];cnt[i]=(cnt[i]%mod+mod)%mod;}while(q--)printf("%lld\n",cnt[lower_bound(d+1,d+cur+1,__gcd(readint(),p))-d]);}
本作品采用知识共享署名-相同方式共享 4.0 国际许可协议进行许可。
本文链接:https://www.q234rty.top/2018/06/11/loj2523/
