【2017多校】HDU6053 TrickGCD 【莫比乌斯】
2017-07-28 16:18
405 查看
枚举gcd(l,r)=d的倍数,则b[i]可能的值为{d,2d,3d,...,floor(a[i]/d)∗d}
则gcd(l,r)=d的倍数时,方案数=∏ni=1a[i]d
显然剩下就是容斥了
而莫比乌斯函数mu[i]=−1k,k=i的素因子个数
ans=∑ni=1{(−mu[i])∗∏nj=1a[j]i}
显然大暴力O(n2)爆炸
维护一个sum[i]=∑nj=1(a[j]<=i)
则确定i,k时,满足a[j]i=k的j数量为sum[(k+1)∗i−1]−sum[k∗i−1]
则gcd=i倍数时的方案数=∏n/ik=1ksum[(k+1)∗i−1]−sum[k∗i−1]
则gcd(l,r)=d的倍数时,方案数=∏ni=1a[i]d
显然剩下就是容斥了
而莫比乌斯函数mu[i]=−1k,k=i的素因子个数
ans=∑ni=1{(−mu[i])∗∏nj=1a[j]i}
显然大暴力O(n2)爆炸
维护一个sum[i]=∑nj=1(a[j]<=i)
则确定i,k时,满足a[j]i=k的j数量为sum[(k+1)∗i−1]−sum[k∗i−1]
则gcd=i倍数时的方案数=∏n/ik=1ksum[(k+1)∗i−1]−sum[k∗i−1]
ans=∑ni=1∏k=n/ik=1ksum[(k+1)∗i−1]−sum[k∗i−1]
最终需要O(nlogn∗(1+12+13+...))=O(nlogn∗调和级数)=大概是...O(nlogn(ln(n+1)+r))#include<stdio.h> #include<iostream> #include<stdlib.h> #include<algorithm> #include<vector> #include<string.h> #include<string> #include<math.h> #include<memory.h> #include<queue> #define ll long long #define pii pair<int,int> #define pll pair<ll,ll> #define MEM(a,x) memset(a,x,sizeof(a)) #define lowbit(x) ((x)&-(x)) using namespace std; //const int inf=0x3f3f3f3f; const int MOD = 1e9+7; const int N = 1e5 + 5; const int inf=MOD; const int MAXN = 100000; bool check[MAXN+10]; int prime[MAXN+10]; int mu[MAXN+10]; void Moblus() { memset(check,false,sizeof(check)); mu[1] = 1; int tot = 0; for(int i = 2; i <= MAXN; i++) { if( !check[i] ){ prime[tot++] = i; mu[i] = -1; } for(int j = 0; j < tot; j++) { if(i * prime[j] > MAXN) break; check[i * prime[j]] = true; if( i % prime[j] == 0){ mu[i * prime[j]] = 0; break; }else{ mu[i * prime[j]] = -mu[i]; } } } } int sum ; int a ; ll qPow(ll a,int n){ ll ans=1; ll t=a%MOD; while(n){ if(n&1){ ans=(ans*t)%MOD; } n>>=1; t=(t*t)%MOD; } return ans; } ll w(int x,int n){ if(sum[x-1]){ return 0; } ll ans=1; for(int i=1;i*x<N-1;++i){ ll t=qPow(i,sum[min((i+1)*x-1,N-1)]-sum[min(N-1,i*x-1)]); ans=(ans*t)%MOD; } return ans; } ll slove(int n){ ll ans=0; for(int i=2;i<=n;++i){ ans+=(-w(i,n)*mu[i])%MOD; ans%=MOD; } return (ans+MOD)%MOD; } int main() { //freopen("/home/lu/code/r.txt","r",stdin); Moblus(); int T; scanf("%d",&T); for(int tt=1;tt<=T;++tt){ int n; MEM(sum,0); scanf("%d",&n); for(int i=1;i<=n;++i){ scanf("%d",&a[i]); ++sum[a[i]]; } for(int i=1;i<N;++i){ sum[i]+=sum[i-1]; } printf("Case #%d: %lld\n",tt,slove(n)); } return 0; }
相关文章推荐
- hdu 6053: TrickGCD (2017 多校第二场 1009) 【莫比乌斯 容斥原理】
- (2017多校训练第二场)HDU - 6053 TrickGCD 初见莫比乌斯
- [莫比乌斯反演] HDU6053: [2017 多校-第2场] TrickGCD
- hdu6053_TrickGCD_莫比乌斯反演_快速幂优化_前缀和
- 2017 杭电多校联赛第二场 1009 TrickGCD(容斥原理) HDU 6053
- HDU6053-TrickGCD 容斥原理+莫比乌斯反演
- [莫比乌斯函数][分段] hdu6053 TrickGCD (2017 Multi-University Training Contest - Team 2)
- HDU 6053 TrickGCD(莫比乌斯反演+分块)
- hdu6053 TrickGCD
- hdu 6134: Battlestation Operational (2017 多校第八场 1002)【莫比乌斯】
- 2017杭电多校联赛第二场-TrickGCD (hdu6053)莫比乌斯容斥
- TrickGCD HDU - 6053 多校2
- 2017多校联合第二场 1009题 hdu 6053 TrickGCD (超详细!!!)莫比乌斯 容斥
- hdu 6053 TrickGCD [2017 Multi-University Training Contest - Team 2] [莫比乌斯函数]
- HDU 6053 TrickGCD(分块+容斥)——2017 Multi-University Training Contest - Team 2
- hdu6053 TrickGCD 容斥原理
- 2017 Multi-University Training Contest - 第二场 09 TrickGCD (容斥+莫比乌斯)
- HDU6053 TrickGCD(2017多校第2场)
- 【数论-莫比乌斯】hdu 6053 TrickGCD
- hdu6053 TrickGCD 莫比乌斯函数 容斥原理