2017多校训练Contest2: 1009 TrickGCD hdu6053

来源:互联网 发布:java数组的定义格式 编辑:程序博客网 时间:2024/06/05 16:27

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
144 4 4 4
 

Sample Output
Case #1: 17

考虑用总数减去gcd为1的答案

那么gcd为1的答案我们只需要容斥一下,所有因子有1的答案-所有因子有2的答案……这样

对于每个因子的加减就是莫比乌斯函数。枚举每个因子的倍数然后前缀和记录区间个数可以做到均摊nlogn的复杂度

#include<queue>#include<vector>#include<cstdio>#include<string>#include<cstring>#include<cassert>#include<iostream>#include<algorithm>using namespace std;int a[100001],ss[1000001];int mu[100001],fai[100001],prime[100001],s[100001];//mu莫比乌斯 fai欧拉 bool check[100001]; int tot;long long mod=1000000007;inline void findfai(){    memset(check,false,sizeof(check));    fai[1]=1; mu[1]=1;    int i,j;    for(i=2;i<=100000;i++)    {        if(!check[i])        {            tot++;            prime[tot]=i;            fai[i]=i-1; mu[i]=-1;        }        for(j=1;j<=tot;j++)        {            if(i*prime[j]>100000)                break;            check[i*prime[j]]=true;            if(i%prime[j]==0)            {                fai[i*prime[j]]=fai[i]*prime[j]; mu[i*prime[j]]=0;                break;            }            else                fai[i*prime[j]]=fai[i]*(prime[j]-1); mu[i*prime[j]]=-mu[i];        }    }    for(i=1;i<=100000;i++)    s[i]=s[i-1]+mu[i];}int n;inline long long power(long long x,int y){long long t=1;while(y!=0){if(y%2==1)t=t*x%mod;x=x*x%mod;y/=2;}return t;}inline long long calc(int x){long long p=1;int i;   for(i=x;i<=100000;i+=x)   {   p=p*power(i/x,ss[i+x-1]-ss[i-1])%mod;   if(i>99999)   {   int dx=1;   dx=11;   }   }return p;}int main(){//freopen("1009.in","r",stdin);//freopen("1009.out","w",stdout);findfai();int T,kk=0;scanf("%d",&T);while(T>0){kk++;T--;scanf("%d",&n);int i;long long xt=1;memset(ss,0,sizeof(ss));for(i=1;i<=n;i++){scanf("%d",&a[i]);xt=(xt*a[i])%mod;ss[a[i]]++;}for(i=1;i<=400000;i++)ss[i]=ss[i-1]+ss[i];sort(a+1,a+1+n);long long ans=0;for(i=1;i<=a[1];i++){ans=(ans+mu[i]*calc(i))%mod;//printf("%lld\n",ans);//int d=100000000;//while(d--);}ans=(xt-ans+mod)%mod;printf("Case #%d: %lld\n",kk,ans);}return 0;}



原创粉丝点击