HDU 6053 TrickGCD —— 2017 Multi-University Training 2

TrickGCD

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

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,Ai1e5
 
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 1e9+7
 
Sample Input
1 4
4 4 4 4
 
Sample Output
Case #1: 17
 
题目大意:有数组A,根据1<=Bi<=Ai,且对于任意1<=l<=r<=n, gcd(Bl,Bl+1...Br)2 构造B数列
思路:B的最小值一定不会大于A的最小值,所以gcd(B1,B2,...,Bn)一定不大于A的最小值,那么我们可以求出A的最小值,对gcd为质数的情况求和,利用容斥原理减去重复的情况。在计算重复情况时,发现对于gcd是奇数个质数的乘积时是加,偶数个时是减,与莫比乌斯函数相反,那么就可以借助莫比乌斯函数求和。这里暴力求和会超时,问了学长之后才知道分桶计算可以快很多,涨姿势了。
 
AC代码:
 1 #include<iostream>
 2 #include<cstring>
 3 #include<cstdio>
 4 using namespace std;
 5 typedef long long LL;
 6 const int MAXN=1e5+10;
 7 const int MOD=1e9+7; 
 8 LL miu[MAXN],primes[MAXN],tot=0;
 9 bool isprime[MAXN];
10 int a[MAXN],sum[MAXN];
11 int maxx=0,minn=MAXN;
12 void getmiu()
13 {
14     memset(isprime, 0, sizeof((isprime)));
15     miu[1]=1;
16     for(int i=2;i<MAXN;i++){
17         if(isprime[i]==false)
18         {
19             miu[i]=-1;
20             primes[++tot]=i;//cout<<'*'<<endl;
21         }
22         for(int j=1;j<=tot;j++){
23             if(i*primes[j]>=MAXN) break;
24             isprime[i*primes[j]]=1;
25             if(i%primes[j]==0){
26                 miu[i*primes[j]]=0;
27                 break;
28             }
29             miu[i*primes[j]]=-miu[i];
30         }
31     }
32     
33     
34     for(int i=1;i<MAXN;i++) miu[i]=-miu[i];
35 }
36 LL quick_pow(LL a, LL p)
37 {
38     int res=1;
39     while(p)
40     {
41         if(p&1) res=a*res%MOD;
42         a=a*a%MOD;
43         p>>=1;
44     }
45     return res;
46 }
47 int solve()
48 {
49     LL i,j,k,p;
50     LL ans=0;
51     for(int i=2;i<=minn;i++){
52         if(!miu[i]) continue;
53         LL res=1;
54         j=min(i, maxx), k=min((i<<1)-1, maxx);
55         for(p=1; ;p++)
56         {
57             if(sum[k]-sum[j-1])
58                 res=res*quick_pow(p, sum[k]-sum[j-1])%MOD;
59             if(k==maxx) break;
60             j+=i;
61             k+=i;
62             if(k>maxx) k=maxx; 
63         }
64         ans+=miu[i]*res;
65         if(ans>MOD) ans-=MOD;
66         if(ans<0) ans+=MOD;
67     }
68     return ans%MOD;
69     
70 }
71 int main()
72 {
73     int T,n,t=0;
74     getmiu();
75     scanf("%d", &T);
76     //cout<<'*'<<endl;
77     while(T--)
78     {
79         scanf("%d", &n);
80         maxx=0,minn=MAXN;
81         memset(sum, 0, sizeof(sum));
82         for(int i=0;i<n;i++){
83             scanf("%d", &a[i]);
84             sum[a[i]]++;
85             maxx=max(a[i], maxx);
86             minn=min(a[i], minn);
87         }
88         for(int i=1;i<=maxx;i++) sum[i]+=sum[i-1];
89         LL res=solve();
90         printf("Case #%d: %lld\n", ++t, res);
91     }
92 }

 

posted @ 2017-07-31 22:33  Bangbangbanana  阅读(327)  评论(0编辑  收藏  举报