Description
Solution
- 首先一个集合 S S S可以把 g c d ( a 1 , a 2 , a 3 , . . . , P ) gcd(a_1,a_2,a_3,...,P) gcd(a1,a2,a3,...,P)的倍数拼出。
- 因此我们把 P , x , a i P,x,a_i P,x,ai分解质因数,把 a i a_i ai根据每一个质因数的次数是否大于 x x x的次数作为二进制数,然后高位后缀和一下,就可以知道某个 T T T的倍数的个数。
- 考虑转移 k k k次对于 f 0 ( S ) f_0(S) f0(S)的贡献实际上是 k n k ∣ S ∣ \frac{k^n}{k^{|S|}} k∣S∣kn,因此一个 S S S的贡献即为 1 ∣ S ∣ \frac{1}{|S|} ∣S∣1。
- 假设某一个数的倍数个数为 c n t cnt cnt(只分辨每一个质因数次数是否大于 x x x),那么这个位置的答案为 ( 1 k + 1 ) c n t − 1 (\frac{1}{k}+1)^{cnt}-1 (k1+1)cnt−1 ,然后高位差分回去得到的 f ( 0 ) f(0) f(0)就是答案了。
- 有点卡常。
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define ll long long
#define mo 1000000007
#define maxn 300005
#define maxm 20
using namespace std;
int T,n,i,j,k,c[maxm],mul[maxm],p[maxm],cnt,cx[maxm],_2[maxm];
ll a[maxn],f[maxn],inv,mulk[maxn],ans,P,x,K;
ll gcd(ll x,ll y){return (x%y==0)?y:gcd(y,x%y);}
ll ksm(ll x,ll y){
ll s=1;
for(;y;y/=2,x=x*x%mo) if (y&1)
s=s*x%mo;
return s;
}
int tot,pri[maxn],bz[maxn];
void getpri(){
for(i=2;i<maxn;i++) {
if (!bz[i]) pri[++tot]=i;
for(j=1;j<=tot&&pri[j]*i<maxn;j++){
bz[i*pri[j]]=1;
if (i%pri[j]==0) break;
}
}
}
int main(){
freopen("ceshi.in","r",stdin);
getpri();for(i=0;i<maxm;i++) _2[i]=1<<i;
scanf("%d%d",&n,&T);
for(i=1;i<=n;i++) scanf("%lld",&a[i]);
while (T--){
scanf("%lld%lld%lld",&x,&K,&P),inv=ksm(K,mo-2);
mulk[0]=1; for(i=1;i<=n;i++) mulk[i]=mulk[i-1]*(inv+1)%mo;
cnt=0;
for(i=1;i<=tot;i++) if (P%pri[i]==0){
ll tmp=P; cnt++,p[cnt]=pri[i],c[cnt]=0;
while (tmp%pri[i]==0) c[cnt]++,tmp/=pri[i];
}
if (x%P==0) x=P; else x=x%P;
for(i=1;i<=cnt;i++) {
cx[i]=0;
while (x%p[i]==0) cx[i]++,x/=p[i];
}
memset(f,0,sizeof(f));
for(i=1;i<=n;i++) {
int s=0; ll tmp=a[i];
for(j=1;j<=cnt&&tmp>1;j++) if (tmp%p[j]==0){
int cc=0;
while (tmp%p[j]==0&&cc<c[j]) tmp/=p[j],cc++;
if (cc>cx[j]) s+=1<<j-1;
}
f[s]++;
}
for(i=0;i<cnt;i++) for(j=_2[cnt]-1;j>=0;j--) if (j>>i&1)
f[j^_2[i]]+=f[j];
for(i=0;i<_2[cnt];i++) f[i]=mulk[f[i]]-1;
for(i=0;i<cnt;i++) for(j=0;j<_2[cnt];j++) if (j>>i&1)
(f[j^_2[i]]-=f[j])%=mo;
printf("%lld\n",(f[0]*ksm(K,n)%mo+mo)%mo);
}
}