题意:
给你一个a序列,让你自己构造b序列,b序列需要满足每个数 bi<=ai 且所有数的gcd>=2.
问你这样的序列有多少个。
题解:
1,筛法
枚举gcd的值,bi的取值最大ai. 所以每个位置有ai/gcd种情况, .然后把这种情况全部弄成一块,快速幂,logn,
最后容斥,把 k*j (j>1)情况减去。
这样n*(logn)^2差点超时。。
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5+5;
const int mod=1e9+7;
#define ll long long
ll v[maxn];
ll sum[maxn];
ll num[maxn];
ll dp[maxn];
ll kru(ll a,ll b){
ll ret=1;
while(b){
if(b&1)
ret=(ret*a)%mod;
b/=2;
a=(a*a)%mod;
}
return ret;
}
int main(){
int T,n;
ll x,y;
scanf("%d",&T);
for(int ca=1;ca<=T;++ca){
memset(v,0,sizeof(v));
memset(sum,0,sizeof(sum));
scanf("%d",&n);
for(int i=1;i<=n;++i){
scanf("%lld",&x);
v[x]++;
}
for(int i=1;i<maxn;++i) sum[i]=sum[i-1]+v[i];
for(int i=2;i<maxn;++i){
num[i]=1;
for(int j=0;j<maxn;j+=i){
int ed=min(maxn-1,j+i-1);
if(j==0) y=sum[ed];
else y=sum[ed]-sum[j-1];
x=j/i;
if(x==0&&y) num[i]=0;
else if(y)
num[i]=(num[i]*kru(x,y))%mod;
}
}
ll ans=0;
for(int i=maxn-1;i>=2;--i){
dp[i]=num[i];
for(int j=i+i;j<maxn;j+=i)
dp[i]=(dp[i]-dp[j]+mod)%mod;
ans=(ans+dp[i])%mod;
}
printf("Case #%d: %lld\n",ca,ans);
}
return 0;
}
莫比乌斯,待补。