HDU 6053 TrickGCD 数论

版权声明:有错误欢迎大家指出。转载请注明出处~ https://blog.csdn.net/black_miracle/article/details/76474357

TrickGCD

Time Limit: 5000/2500 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)
Total Submission(s): 2532    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,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

题意:问能构造多少序列  满足1<=bi<=ai且gcd(ai)>=2


题解:莫比乌斯搞一搞

for i

i代表当前gcd是i的倍数

然后用莫比乌斯容斥一下


#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
const ll mod=1000000007;
ll quick(ll a,ll k){
    ll ans=1;
    while(k){
        if(k&1)ans=ans*a%mod;
        k/=2;
        a=a*a%mod;
    }
    return ans;
}
int mu[100005],cas=0;
void mobius(int mn)
{
    mu[1]=1;
    for(int i=1;i<=mn;i++){
        for(int j=i+i;j<=mn;j+=i){
            mu[j] -= mu[i];
        }
    }
}
ll a[200005],cnt[200005];
int main(){
    int t,cas=1;
    mobius(100000);
    scanf("%d",&t);
    while(t--){
        ll n,m,i,j;
        ll mis=999999;
        scanf("%lld",&n);
        memset(cnt,0,sizeof(cnt));
        memset(a,0,sizeof(a));
        for(i=1;i<=n;i++){
            ll x;
            scanf("%lld",&x);
            a[x]++;
            mis=min(x,mis);
        }
        for(i=1;i<=200000;i++){
            cnt[i]=cnt[i-1]+a[i];
        }
        ll ans=0;
        for(i=2;i<=mis;i++){
            ll temp=1;
            for(j=1;i*j<=100000;j++){
                temp=(temp*quick(j,cnt[i*j+i-1]-cnt[i*j-1])%mod);
            }
            ans=(ans-temp*mu[i]+mod)%mod;
        }
        printf("Case #%d: %lld\n",cas++,(ans%mod+mod)%mod);
    }
    return 0;
}


猜你喜欢

转载自blog.csdn.net/black_miracle/article/details/76474357