您的位置:首页 > 其它

2017多校第二场 HDU 6053 TrickGCD 莫比乌斯反演

2017-07-29 09:53 543 查看
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

题意:给出长度为n的A数列,求满足条件的B数组的个数,条件:①1<=b[i]<=a[i] ②对于任意区间【L,R】,区间gcd>=2

解法:除了上一篇文章的容斥求法,还有可以直接利用Mobius来求。对于某个数及其倍数能产生的B数组方案个数为:



但其中会产生重复的数列,这时候我们需要判断x的质因子数的奇偶性,若为奇数则加上该方案数,否则减去该方案数(容斥原理)可以用莫比乌斯函数判断当前枚举的GCD对答案的贡献。

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int maxn = 1e5+7;
const int huyu = 1e9+7;
LL mu[maxn], num[2*maxn], ks = 0;
void Mobius(LL n){
mu[1] = 1;
for(LL i=1; i<=n; i++){
for(LL j=i+i; j<=n; j+=i){
mu[j]-=mu[i];
}
}
}
LL qsm(LL b, LL n){
LL ret = 1;
while(n){
if(n&1) ret = ret*b%huyu;
b=b*b%huyu;
n>>=1;
}
return ret;
}

int main()
{
Mobius(100000);
int T,n;
scanf("%d", &T);
while(T--)
{
memset(num, 0, sizeof(num));
scanf("%d", &n);
int mi = 1e9;
for(int i=1; i<=n; i++){
int x;
scanf("%d", &x);
mi = min(mi, x);
num[x]++;
}
for(int i=1; i<=200000; i++){
num[i]+=num[i-1];
}
LL sum = 0;
for(LL i=2; i<=mi; i++){
LL f = 1;
for(LL j=1; j*i<=100000; j++){
f = (f*qsm(1LL*j, num[(j+1)*i-1]-num[j*i-1]))%huyu;
}
sum = ((sum - f * mu[i]% huyu) + huyu) %huyu;
}
printf("Case #%d: ", ++ks);
printf("%lld\n",sum);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: