HDU 6053 ( TrickGCD ) 分块+容斥

Posted liylho

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDU 6053 ( TrickGCD ) 分块+容斥相关的知识,希望对你有一定的参考价值。

TrickGCD

Time Limit: 5000/2500 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)
Total Submission(s): 3401    Accepted Submission(s): 1268


Problem Description
You are given an array A , and Zhu wants to know there are how many different array B satisfy the following conditions?

1BiAi
* For each pair( l , r ) (1lrn) , gcd(bl,bl+1...br)2
 

 

Input
The first line is an integer T(1T10) describe the number of test cases.

Each test case begins with an integer number n describe the size of array A.

Then a line contains n numbers describe each element of A

You can assume that 1n,Ai105
 

 

Output
For the kth test case , first output "Case #k: " , then output an integer as answer in a single line . because the answer may be large , so you are only need to output answer mod 109+7
 

 

Sample Input
1 4 4 4 4 4
 

 

Sample Output
Case #1: 17
 

 

Source
 
思路:枚举gcd ,对于当前的i,分区间地计算出gcd为i倍数的数列总数,之后利用容斥来减掉重复的部分,要保证每次减掉都是确定的倍数因此要倒着减。
代码:
 1 #include<bits/stdc++.h>
 2 #define db double
 3 #define ll long long
 4 #define ci(x) scanf("%d",&x)
 5 #define cd(x) scanf("%lf",&x)
 6 #define cl(x) scanf("%lld",&x)
 7 #define pi(x) printf("%d\n",x)
 8 #define pd(x) printf("%f\n",x)
 9 #define pl(x) printf("%lld\n",x)
10 #define fr(i,a,b) for(int i=a;i<=b;i++)
11 using namespace std;
12 const int N=1e5+5;
13 const int mod=1e9+7;
14 const int MOD=mod-1;
15 const db  eps=1e-10;
16 const int inf = 0x3f3f3f3f;
17 ll a[N];
18 ll sum[N];
19 ll qpow(ll x,ll n)
20 {
21     ll ans=1;x%=mod;
22     for(;n>0;n>>=1){if(n&1) ans=(ans*x)%mod;x=x*x%mod;}
23     return ans;
24 }
25 int main()
26 {
27 //    ios::sync_with_stdio(false);
28 //    cin.tie(0);
29     int t;
30     ci(t);
31     for(int ii=1;ii<=t;ii++)
32     {
33         int n,x,ma=-N,mi=N;
34         memset(sum,0,sizeof(sum));
35         ci(n);
36         for(int i=0;i<n;i++)
37             ci(x),sum[x]++,ma=max(ma,x),mi=min(mi,x);
38         for(int i=1;i<=ma;i++) sum[i]+=sum[i-1];//统计小于等于i的数字的个数
39         for(int i=2;i<=mi;i++){//从2~mi枚举gcd
40             a[i]=1;
41             for(int j=i;j<=ma;j+=i){//分区间计算
42                 int c;
43                 if(i+j-1<=ma) c=sum[i+j-1]-sum[j-1];
44                 else c=sum[ma]-sum[j-1];
45                 if(!c) continue;
46                 a[i]=(a[i]*qpow(j/i,c))%mod;
47             }
48         }
49         ll ans=0;
50         for(int i=mi;i>=2;i--)
51         {
52             for(int j=i+i;j<=mi;j+=i) a[i]=(a[i]-a[j])%mod;//减掉确定的倍数
53             a[i]=(a[i]+mod)%mod;
54             ans=(ans+a[i])%mod;
55         }
56         printf("Case #%d: %lld\n",ii,ans);
57     }
58 }

 

以上是关于HDU 6053 ( TrickGCD ) 分块+容斥的主要内容,如果未能解决你的问题,请参考以下文章

HDU 6053 ( TrickGCD ) 分块+容斥

HDU 6053 TrickGCD(分块)

HDU 6053 TrickGCD 容斥

hdu 6053 TrickGCD (莫比乌斯)

HDU 6053 TrickGCD 莫比乌斯函数/容斥/筛法

hdu6053(莫比乌斯+容斥+分块)