You are given an array
A
, and Zhu wants to know there are how many different array
B
satisfy the following conditions?
*
1≤Bi≤Ai
* For each pair( l , r ) (
1≤l≤r≤n
) ,
gcd(bl,bl+1...br)≥2
You can assume that
1≤n,Ai≤105
分析:限制等价于gcd(1,n) >= 2,那么我们考虑分别计算gcd是2的倍数,gcd是3的倍数...gcd是k的倍数..然后相加,这样当然会有重复,所以我们只要在系数上乘上一个莫比乌斯函数就可以了,但是这样暴力枚举gcd后还要计算ai/k,还是n^2的,我们注意到n/k的取值随着k增大而减小,而且sum(n/k)是n*logn级别的,所以我们考虑直接枚举ai/k的解,然后事先对所有ai的值求一个前缀和,这样直接枚举ai/k的解j就可以了.
#include <bits/stdc++.h> #define N 100005 #define INF 1000000007 #define MOD 1000000007 using namespace std; typedef long long ll; bool vis[N]; int t,prime[N],cnt,n,Time,mu[N],a[N],f[N]; ll ans; void init_mu() { memset(vis,0,sizeof(vis)); mu[1] = 1; cnt = 0; for(int i = 2;i < N;i++) { if(!vis[i]) { prime[cnt++] = i; mu[i] = -1; } for(int j = 0;j < cnt && i*prime[j] < N;j++) { vis[i*prime[j]] = 1; if(i % prime[j]) mu[i*prime[j]] = -mu[i]; else { mu[i*prime[j]] = 0; break; } } } } ll ksm(ll x,ll y) { ll ans = 1; while(y) { if(y & 1) ans = ans * x % MOD; x = x * x % MOD; y >>= 1; } return ans; } int main() { init_mu(); scanf("%d",&t); while(t--) { ans = 0; memset(f,0,sizeof(f)); scanf("%d",&n); int Min = INF; for(int i = 1;i <= n;i++) { scanf("%d",&a[i]); Min = min(a[i],Min); f[a[i]]++; } for(int i = 1;i < N;i++) f[i] += f[i-1]; for(int i = 2;i <= Min;i++) { ll temp = 1; for(int j = i;j < N;j += i) temp = temp * ksm(j/i,f[min(j+i-1,N-1)] - f[j-1]) % MOD; ans = (ans + temp*mu[i]*-1 + MOD) % MOD; } cout<<"Case #"<<++Time<<": "<<ans<<endl; } }