cf 645F Cowslip Collections 组合数学 + 简单数论

http://codeforces.com/contest/645/problem/F
F. Cowslip Collections
time limit per test

8 seconds

memory limit per test

512 megabytes

input

standard input

output

standard output

In an attempt to make peace with the Mischievious Mess Makers, Bessie and Farmer John are planning to plant some flower gardens to complement the lush, grassy fields of Bovinia. As any good horticulturist knows, each garden they plant must have the exact same arrangement of flowers. Initially, Farmer John has n different species of flowers he can plant, with ai flowers of the i-th species.

On each of the next q days, Farmer John will receive a batch of flowers of a new species. On day j, he will receive cj flowers of the same species, but of a different species from those Farmer John already has.

Farmer John, knowing the right balance between extravagance and minimalism, wants exactly k species of flowers to be used. Furthermore, to reduce waste, each flower of the k species Farmer John chooses must be planted in some garden. And each of the gardens must be identical; that is to say that each of the k chosen species should have an equal number of flowers in each garden. As Farmer John is a proponent of national equality, he would like to create the greatest number of gardens possible.

After receiving flowers on each of these q days, Farmer John would like to know the sum, over all possible choices of k species, of the maximum number of gardens he could create. Since this could be a large number, you should output your result modulo 109 + 7.

Input

The first line of the input contains three integers n, k and q (1 ≤ k ≤ n ≤ 100 000, 1 ≤ q ≤ 100 000).

The i-th (1 ≤ i ≤ n) of the next n lines of the input contains an integer ai (1 ≤ ai ≤ 1 000 000), the number of flowers of species i Farmer John has initially.

The j-th (1 ≤ j ≤ q) of the next q lines of the input contains an integer cj (1 ≤ cj ≤ 1 000 000), the number of flowers of a new species Farmer John receives on day j.

Output

After each of the q days, output the sum of the maximum possible number of gardens, where the sum is taken over all possible choices of k species, modulo 109 + 7.

Examples
Input
3 3 2
4
6
9
8
6
Output
5
16
Input
4 1 2
6
5
4
3
2
1
Output
20
21
Note

In the first sample case, after the first day Farmer John has (4, 6, 9, 8) of each type of flower, and k = 3.

Choosing (4, 6, 8) lets him make 2 gardens, each with (2, 3, 4) of each flower, respectively. Choosing (4, 6, 9), (4, 9, 8) and (6, 9, 8) each only let him make one garden, since there is no number of gardens that each species can be evenly split into. So the sum over all choices of k = 3 flowers is 2 + 1 + 1 + 1 = 5.

After the second day, Farmer John has (4, 6, 9, 8, 6) of each flower. The sum over all choices is 1 + 2 + 2 + 1 + 1 + 2 + 2 + 3 + 1 + 1 = 16.

In the second sample case, k = 1. With x flowers Farmer John can make x gardens. So the answers to the queries are 6 + 5 + 4 + 3 + 2 = 20 and 6 + 5 + 4 + 3 + 2 + 1 = 21.

题意:

n,k,q <= 10^5,ai <= 10^6

一个数组,初始长度为n,元素为a1~an

接下来有q天,每一天会向数组里面新加入一个数,第i天元素个数有n + i个

数组取k个元素有C(n + i , k )种方案,求每一个种方案的k的数的gcd之和

思路:

这道题目明显具有阶段性,向其中加入一个数cur后,求解ans不用重新计算一遍,只需要考虑cur取的情况,再从之前的数中取k - 1 个数(1),求gcd之和,再累加上以前的答案即可

对于(1)所有方案,gcd一定是cur的约数,所以我们考虑枚举cur的约数

用一个数组f[i]表示cur之前的数中,是i的倍数的数的个数

对于约数x

ans += C(f[x],k - 1) * x,但是此时把一些gcd是x的倍数的情况也算进去了

反过来说,对于x,我们要把x的约数多算的部分给退回去,差不多就是容斥那样

推一下公式,定义

g[i] = i - sigma(g[d],d < i && d | i)

这样相当于是给每一个数一个权值,这样就不用再去考虑重复计算的情况了

这样对于cur的约数x

ans += C(f[x],k - 1) * g[x]

复杂度O(sqrt(10^6)) = O(10^3)

总复杂度 = O(10 ^ 9 + 10 ^ 3 * 10 * 5) = O(10 ^ 9 + 10 ^ 8)

1.预处理:

jie[i] = i!

comb[i] = C(i,k - 1)

g[i] = i - sigma(g[d],d < i && d | i) (1 <= i <= 10 ^ 6,d是i的约数且 != i)

(预处理g的复杂度=10 ^ 6 * 10 ^ 3 = 10 ^ 9)

   //File Name: cf645F.cpp
//Author: long
//Mail: 736726758@qq.com
//Created Time: 2016年05月15日 星期日 19时58分07秒 #include <stdio.h>
#include <algorithm>
#include <iostream>
#include <string.h>
#include <vector>
#include <math.h> #define LL long long
#define pb push_back using namespace std; const int MAXN = + ;
const int MAXM = + ;
const int MOD = (int)1e9 + ; LL jie[MAXN << ];
LL comb[MAXN << ];
LL ans;
int g[MAXM];
int f[MAXM];
vector<int> di; void get_di(int x){
di.clear();
int ma = (int)sqrt(x + 0.5);
for(int i=,j;i<=ma;i++){
if(x % i == ){
di.pb(i);
j = x / i;
if(j != i)
di.pb(j);
}
}
} LL qp(LL x){
LL res = ,y = MOD - ;
while(y){
if(y & ) res = res * x % MOD;
x = x * x % MOD;
y >>= ;
}
return res;
} void init(int n,int k){
ans = ;
jie[] = ;
for(int i=;i<=n;i++){
jie[i] = jie[i - ] * i % MOD;
}
for(int i=;i<=n;i++){
if(i < k) comb[i] = ;
else comb[i] = jie[i] * qp(jie[k] * jie[i - k] % MOD) % MOD;
}
for(int i=,ma;i<=MAXM;i++){
g[i] = i;
get_di(i);
ma = di.size();
for(int j=;j<ma;j++){
if(di[j] == i) continue;
g[i] -= g[di[j]];
}
}
} void query(int x){
get_di(x);
int ma = di.size();
for(int i=;i<ma;i++){
(ans += comb[f[di[i]]++] * g[di[i]] % MOD ) %= MOD;
}
} void solve(int n,int k,int q){
init(n + q,k - );
for(int i=,a;i<=n;i++){
scanf("%d",&a);
query(a);
}
for(int i=,a;i<=q;i++){
scanf("%d",&a);
query(a);
printf("%d\n",ans);
}
} int main(){
int n,k,q;
scanf("%d %d %d",&n,&k,&q);
solve(n,k,q);
return ;
}
上一篇:《敏捷软件开发:原则、模式与实践(C#版.修订版)》—第2章2.3节 参考文献


下一篇:【原】cpu消耗高,查看对应的线程栈信息