1. 程式人生 > >【 hdu 6053】 TrickGCD 【數論 容斥 + 莫比烏斯函式 】

【 hdu 6053】 TrickGCD 【數論 容斥 + 莫比烏斯函式 】

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

  • 1≤Bi≤Ai
  • For each pair( l , r ) (1≤l≤r≤n) , gcd(bl,bl+1…br)≥2

Input
The first line is an integer T(1≤T≤10) 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 1≤n,Ai≤105

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
2017 Multi-University Training Contest - Team 2

題解連結
程式碼

#include<bits/stdc++.h>
#define LL long long 
using namespace std;
const int mod = 1e9+7;
const int MAXN = 100200;
const int inf  =  0x3f3f3f3f;
bool su[MAXN]; 
int prime[MAXN],miu[MAXN];
void init(){
    int
cnt = 0; miu[1] = 1; for(LL i = 2; i < MAXN; i++){ if(!su[i]){ prime[cnt++] = i; miu[i] = -1; } for(LL j = 0; j < cnt && i*prime[j] < MAXN; j++){ su[i*prime[j]] = 1; if(i % prime[j]) miu[i*prime[j]] = -miu[i]; else{ miu[i*prime[j]] = 0; break; } } } } inline LL qp(LL a,LL b){ LL s=1,base=a%mod; while(b){ if(b&1) s=s*base%mod; base=base*base%mod; b>>=1; } return s; } int num[MAXN],suma[MAXN*2]; int main(){ int t,ncase = 1,n,v,maxa,mina; scanf("%d",&t); init(); while(t--){ LL ans = 0;maxa = -inf,mina = inf; scanf("%d",&n); memset(num,0,sizeof(num)); for(int i = 1;i <= n;i++){ scanf("%d",&v); num[v]++; mina = min(mina,v);maxa = max(maxa,v); } for(int i = 1;i <= maxa*2;i++){ suma[i] = suma[i-1] + num[i]; } LL temp = 1; for(int i = 2;i <= mina;i++){ temp = 1; for(int j = 1;j*i <= maxa;j++){ temp *= qp(j,(suma[i*j+i-1]-suma[i*j-1])); temp %= mod; } ans -= miu[i]*temp;ans %= mod; } printf("Case #%d: %lld\n",ncase++,(ans+mod)%mod); } }