TrickGCD
Time Limit: 5000/2500 MS (Java/Others) Memory Limit: 262144/262144 K (Java/Others)Total Submission(s): 2731 Accepted Submission(s): 1027
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
* 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
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
k
th 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
题意:给出一个数组A 要你求出数组B的种数,其中对B有一些要求 就是Bi < Ai 并且满足所有Bi 里的gcd 不为 1,就是不互质
思路 : 先求一个前缀和 把对于k来说比它小的数的数量统计起来,然后从最小的数开始去求以它为gcd时候的组合种数,由于两个不互质的数的组合种数有重复算的部分
于是我们采用莫比乌斯反演来对它进行容斥。
代码如下
#include<stdio.h>
#include<string.h>
#define ll long long
#define mod 1000000007
#define MAXN 200005
#define INF 0xfffffff
ll mub[100005];
void Mobius(){
mub[1] = 1;
for(int i = 1;i <= 100000;i++){
for(int j = i + i;j <= 100000;j += i){
mub[j] -= mub[i];
}
}
}
ll Pow(ll a,ll b){
ll ans = 1;
while(b){
if(b & 1){
ans *= a;
ans %= mod;
}
a *= a;
a %= mod;
b /= 2;
}
return ans;
}
ll a[MAXN],sum[MAXN],k,Min;
int main(){
Mobius();
int n,t,Case = 1;
scanf("%d",&t);
while(t--){
scanf("%d",&n);
memset(a,0,sizeof(a));
Min = INF;
for(int i = 1;i <= n;i++){
scanf("%lld",&k);
a[k]++;
Min = k < Min ? k : Min;
}
ll ans = 0;
sum[0] = 0;
for(int i = 1;i < 200000;i++){
sum[i] = sum[i - 1] + a[i];
}
for(int i = 2;i <= Min;i++){
ll temp = 1;
for(int j = 1;j * i <= 100000;j++){
temp = (temp * Pow((ll)j,sum[i * j + i - 1] - sum[i * j - 1])) % mod;
}
ans = (ans - temp * mub[i] + mod) % mod;
}
printf("Case #%d: %lld\n",Case++,ans);
}
return 0;
}