和某道即将被出到比赛上的题似乎很类似
首先如果要求$gcd=i$,那么对于不是$i$的倍数的数字是一定需要修改的,剩余的随便抽出来必须修改的个数然后快速幂搞一搞就行了
设$x$表示有多少个$a$中的数,是$i$的倍数
$y=n-x$,既不是$i$的倍数的数的个数
$z=y-k$,既刨去掉必须修改的,选择性必须修改的有这么多(只能修改$i$的倍数的数)
当然这么凑出来的可能$gcd$是$i$的倍数,因此还需要去掉
则对于$i$的答案为
$$f(i)=\lfloor \frac{m}{i} \rfloor^y {x \choose z} (\lfloor \frac{m}{i} \rfloor-1)^z - \sum_{i \mid d}f(d)$$
1 #include <bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 template<typename T> inline void read(T &x) { 5 char c = x = 0; 6 while(!isdigit(c)) c = getchar(); 7 while(isdigit(c)) x = x * 10 + c - '0', c = getchar(); 8 } 9 10 const int N = 3e5 + 10, mod = 1e9 + 7; 11 12 int n, m, k, a[N], fac[N], invfac[N], vis[N]; 13 14 ll pw(ll a, ll b) { 15 ll r = 1; 16 for( ; b ; b >>= 1, a = a * a % mod) 17 if(b & 1) 18 r = r * a % mod; 19 return r; 20 } 21 22 ll f[N]; 23 24 ll C(ll n, ll m) { 25 if(n < m) return 0; 26 return 1ll * fac[n] * invfac[m] % mod * invfac[n - m] % mod; 27 } 28 29 int main() { 30 read(n), read(m), read(k); 31 for(int i = 1 ; i <= n ; ++ i) read(a[i]); 32 fac[0] = 1, invfac[0] = 1; 33 for(int i = 1 ; i <= n ; ++ i) fac[i] = 1ll * fac[i - 1] * i % mod, invfac[i] = pw(fac[i], mod - 2); 34 for(int i = 1 ; i <= n ; ++ i) 35 vis[a[i]] ++; 36 for(int i = 1 ; i <= m ; ++ i) { 37 int x = 0; 38 for(int j = i ; j <= m ; j += i) { 39 x += vis[j]; 40 } 41 int y = n - x; 42 if(y > k) continue; 43 int z = k - y; 44 f[i] = pw(m / i, y) * C(x, z) % mod * pw(m / i - 1, z) % mod; 45 } 46 for(int i = m ; i ; -- i) { 47 for(int j = i + i ; j <= m ; j += i) { 48 f[i] = (1ll * f[i] - f[j]) % mod; 49 } 50 } 51 for(int i = 1 ; i <= m ; ++ i) { 52 ll ans = (1ll * f[i] + mod) % mod; 53 if(i > 1) putchar(' '); 54 printf("%lld", ans); 55 if(i == m) puts(""); 56 } 57 }