2017 多校2 hdu 6053 TrickGCD
题目:
You are given an array (A) , and Zhu wants to know there are how many different array (B) satisfy the following conditions?
- (1≤B_i≤A_i)
- 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,A_i≤10^{5})
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 (10^{9}+7)
思路:
枚举(g = gcd(b_1,b_2,....,b_n)),
那么(gcd为g)的倍数的答案就是(prod_{i=1}^{n}frac{A_i}{g})
每次暴力计算是不行的,想到一个数在(g到2g-1)除以g结果是不变的
所以可以预处理区间数字个数的前缀和,(O(nlogn))类似素数筛法预处理出每个(g)的答案
现在要计算(gcd为g)的答案,我们从大到小枚举,同时更新它的约数的答案,就可以保证不重复了
从小到大枚举过去就要用到莫比乌斯函数去计算了
(令F(i)为gcd为i的倍数的方案数,f(i)为gcd为i的方案数)
(F(i) = sum_{i|d}^{}{f(d)}
ightarrow f(i) = sum_{i|d}u(frac{d}{i})F(d))
代码贴的是比赛时过的姿势
#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int> P;
typedef long long LL;
const int mod = 1e9 + 7;
const int N = 1e5 + 10;
vector<int> v[N];
int n;
int sum[N],ans[N];
void init(){
for(int i = 2;i < N;i++){
for(int j = i;j < N;j+=i) v[j].push_back(i);
}
}
int qpow(int x,int y){
int ans = 1;
while(y){
if(y&1) ans = 1LL* ans * x % mod;
x = 1LL * x * x % mod;
y >>= 1;
}
return ans;
}
int main(void)
{
init();
int T, x;
int cas = 1;
cin>>T;
while(T--){
memset(sum, 0, sizeof(sum));
scanf("%d",&n);
int mi = N;
for(int i = 1;i <= n;i++) {
scanf("%d",&x);
mi = min(x,mi);
sum[x]++;
}
for(int i = 1;i < N;i++) sum[i]+=sum[i-1];
for(int i = 2;i <= mi;i++){
ans[i] = 1;
for(int j = i;j < N;j+=i){
int l = j + i - 1 > N - 1?N-1:j + i - 1;
ans[i] = 1LL * ans[i] * qpow(j / i,sum[l] - sum[j - 1]) % mod;
}
}
int res = 0;
for(int i = mi;i >= 2;i--){
res = (res + ans[i])%mod;
for(int j = 0;j < v[i].size();j++) ans[v[i][j]] = (ans[v[i][j]] - ans[i] + mod)%mod;
}
printf("Case #%d: %d
",cas++,res);
}
return 0;
}