HDU 6053 TrickGCD(莫比乌斯反演+分块)
2017-07-27 22:15
281 查看
题目链接
TrickGCD分析
题意其实很简单,反过来其实只要求得 gcd(bi)=1 的个数,然后再用总的组合数减去就行了而对于求 gcd(bi)=1,bi<=Ai 由mobius公式
∑x=1min{Ai}μ(x)∏i=1nfloor(Ai/x)
关键就在于如何快速计算它的值,这里我采用的是 nlogn 的算法.用 sum[i] 表示 Aj<=i的数的总数 对于每一个 x 连续倍数的一段(比如i−1,i+d−1 这一段除d都是i/d)的值是相同,我们就可以直接求个幂次(sum[i+d−1]−sum[i−1])这样总的复杂度就是 O(nlogn) 在乘以快速幂的复杂度
//Problem : 6053 ( TrickGCD ) Judge Status : Accepted //RunId : 21361279 Language : G++ Author : zouzhitao //Code Render Status : Rendered By HDOJ G++ Code Render Version //0.01 Beta #include<bits/stdc++.h> #define pb push_back #define mp make_pair #define PI acos(-1) #define fi first #define se second #define INF 0x3f3f3f3f #define INF64 0x3f3f3f3f3f3f3f3f #define random(a,b) ((a)+rand()%((b)-(a)+1)) #define ms(x,v) memset((x),(v),sizeof(x)) using namespace std; const int MOD = 1e9+7; const double eps = 1e-8; typedef long long LL; typedef long double DB; typedef pair<int,int> Pair; const int maxn = 1e5+10; int mu[maxn],prime[maxn],cnt; int sum[maxn]; void mobius(){ cnt =0; mu[1] = 1; memset(prime,0,sizeof(prime)); for(int i = 2 ; i<maxn ; ++i){ if(!prime[i]){ prime[cnt++] = i; mu[i] =-1; } for(int j=0 ; j<cnt && i*prime[j]<maxn ; ++j){ prime[i*prime[j]] = 1; if(i%prime[j])mu[prime[j]*i] = -mu[i]; else { mu[i*prime[j]] = 0; break; } } } // sum_mu[0] = 0; // for(int i=1 ; i<maxn ; ++i) // sum_mu[i] = sum_mu[i-1]+mu[i]; } LL power_mod(LL x,LL n){ LL ret =1; while (n) { if(n&1)ret = ret*x %MOD; x= x*x %MOD; n >>=1; } return ret; } int num[maxn]; inline LL F(){ int sz =0; for(int i=1; i<maxn ; ++i) if(num[i]){sz= i;break;} int maxv = 0; for(int i=maxn-1 ; i>=0 ; --i) if(num[i]){ maxv = i;break; } maxv++; LL ans = 0; for(int d = 1 ; d <=sz; ++d){ LL val =mu[d]; if(val) for(int i=d; i<maxv ; i+=d){ val *= power_mod(i/d,sum[min(i+d,maxv)-1]- sum[i-1]); val %= MOD; } ans += val; ans %=MOD; } return ans; } int main() { // std::ios::sync_with_stdio(false); // std::cin.tie(0); int n; mobius(); int T; scanf("%d",&T ); int kase = 0; while (T--) { int n; scanf("%d",&n ); ms(num,0); sum[0] = 0; for(int i=1; i<=n ; ++i){ int x; scanf("%d", &x);;num[x]++; } for(int i=1 ; i<maxn ; ++i){ sum[i] = sum[i-1] + num[i]; } LL ans = F(); LL val = 1; for(int i=1 ; i<maxn ; ++i){ val *= power_mod(i,num[i]); val %= MOD; } printf("Case #%d: %lld\n",++kase,(val-ans+MOD) %MOD ); } return 0; }
相关文章推荐
- 2017多校第二场 HDU 6053 TrickGCD 莫比乌斯反演
- (2017多校训练第二场)HDU - 6053 TrickGCD 初见莫比乌斯
- 2017多校联合第二场 1009题 hdu 6053 TrickGCD (超详细!!!)莫比乌斯 容斥
- HDU 6053 TrickGCD(分块)
- TrickGCD(HDU 6053 莫比乌斯函数的反演)
- hdu 6053 TrickGCD 筛法+莫比乌斯函数+分块处理
- HDU 6053 TrickGCD (莫比乌斯函数+分块筛)
- hdu 1695 GCD(莫比乌斯反演+分块模板)
- hdu 6053: TrickGCD (2017 多校第二场 1009) 【莫比乌斯 容斥原理】
- HDU 6053 TrickGCD(分块+容斥)——2017 Multi-University Training Contest - Team 2
- hdu 6053 TrickGCD 容斥 莫比乌斯
- HDU - 6053 TrickGCD(莫比乌斯反演+容斥思想+分块前缀和技巧)
- 【数论-莫比乌斯】hdu 6053 TrickGCD
- HDU 莫比乌斯反演 1695 GCD
- 【HDU 6053 TrickGCD】 + 莫比乌斯反演
- HDU 1695 GCD(莫比乌斯反演,入门)
- HDU 6053 TrickGCD(莫比乌斯反演)
- SPOJ PGCD - Primes in GCD Table (好题! 莫比乌斯反演+分块求和优化)
- [莫比乌斯反演+分块求和] BZOJ2820: YY的GCD
- TrickGCD HDU - 6053 多校2