2017多校訓練Contest2: 1009 TrickGCD hdu6053

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

考慮用總數減去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;
}



發佈了406 篇原創文章 · 獲贊 16 · 訪問量 24萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章