题意
给出一个长度为n的数列A,求有多少个不同的长度为n的B数列满足下列限制:
1≤Bi≤Ai
For each pair(L,R)(1≤L≤R≤n),gcd(BL,BL+1,...,BR)≥2
n,ai≤100000
有T组数据,
T≤10
题解
第一次打
HDU
多校,全场抱大腿,都靠两位学长……
先转换一下,题目说的第二个条件显然就等价于
gcd(B1,...,Bn)>=2
.
然后可以容斥一下,就求满足
gcd(B1,...,Bn)=1
的方案数即可。
开始推式子:
∑i1=1a1∑i2=1a2...∑in=1an[gcd(i1,...,in)=1]
∑i1=1a1∑i2=1a2...∑in=1an∑d|gcd(..)μ(k)
∑d=1min(a)∑d|i1a1∑d|i2a2...∑d|inanμ(d)
∑d=1min(a)μ(d)∏i=1n⌊aid⌋
然后如果按照传统方法枚举除法分块搞, ∏ni=1⌊aid⌋ 有 nn√ 段。这样是 O(n2n√∗T) 的,会 T 掉。
怎么做呢?可以换个思路,对于每次算
具体来说:
∑d=1min(a)μ(d)∏t=1max(a)/dtx,(x为满足⌊aid⌋=t的i的个数)
x 怎么求?
复杂度的话 n+n/2+n/3+... 这样的东西约为 nlogn 。在加上快速幂,共 O(nlog2n∗T) 。
看上去好像有点危险,但是快速幂的 log 很小,常数也小,是可以过的。
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
inline char gc(){
static char buf[100000],*p1=buf,*p2=buf;
return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
inline int getint(){
char ch=gc(); int res=0,ff=1;
while(!('0'<=ch&&ch<='9')) ch=='-'?ff=-1:0, ch=gc();
while('0'<=ch&&ch<='9') res=(res<<3)+(res<<1)+ch-'0', ch=gc();
return res*ff;
}
const int maxn=200005, N=200000, MOD=1000000007;
typedef long long LL;
int _test,n,ans,_min,_max,a[maxn],sum[maxn],p[maxn],mu[maxn];
bool vis[maxn];
void get_mu(){
memset(vis,1,sizeof(vis));
mu[1]=1;
for(int i=2;i<=N;i++){
if(vis[i]) p[++p[0]]=i, mu[i]=-1;
for(int j=1;j<=p[0]&&(LL)i*p[j]<=N;j++){
vis[i*p[j]]=false;
if(i%p[j]==0){ mu[i*p[j]]=0; break; }
mu[i*p[j]]=-mu[i];
}
}
}
int Pow(int a,int b){
LL res=1;
for(LL w=a;b;b>>=1,w=w*w%MOD) if(b&1) res=(res*w)%MOD;
return res;
}
void Solve(){
ans=0;
for(int d=1;d<=_min;d++){
LL res=(mu[d]+MOD)%MOD;
for(int t=1;t<=_max/d;t++) res=res*Pow(t,sum[(t+1)*d-1]-sum[t*d-1])%MOD;
ans=(ans+res)%MOD;
}
}
int main(){
freopen("hdu6053.in","r",stdin);
freopen("hdu6053.out","w",stdout);
get_mu();
scanf("%d",&_test);
for(int ii=1;ii<=_test;ii++){
memset(sum,0,sizeof(sum));
n=getint(); _min=1e+9; _max=0; LL tot=1;
for(int i=1;i<=n;i++) sum[a[i]=getint()]++, tot=(tot*a[i])%MOD, _min=min(_min,a[i]), _max=max(_max,a[i]);
for(int i=1;i<=N;i++) sum[i]+=sum[i-1];
Solve();
printf("Case #%d: %d\n",ii,((tot-ans)%MOD+MOD)%MOD);
}
return 0;
}