Description
给出
[n=prod_{i=1}^{w}p_i^{a_i}
]
求出:
[sum_{i=1}^{n}[gcd(i,n)=1]i^d
]
(dle 10^2,wle 10^3),答案对 (10^9+7) 取模。
Solution
[sum_{i=1}^{n} [gcd(i,n)=1]i^d
]
[=sum_{i=1}^{n} (sum_{k|iwedge k|n}mu(k))i^d
]
[=sum_{k|n} mu(k)k^d(sum_{i=1}^{frac{n}{k}}i^d)
]
对于后面那一坨我们知道可以写成:
[sum_{i=1}^{d+1} f_i(frac{n}{k})^i
]
所以原式可以写成:
[=sum_{k|n}mu(k)k^dsum_{i=1}^{d+1}f_i(frac{n}{k})^i
]
[=sum_{i=1}^{d+1}f_in^isum_{k|n}mu(k)k^{d-i}
]
我们可以观察到后面那一坨因为含有 (mu(k)),所以所有能够产生贡献的 (k) 的指数最大值不会超过 (1),所以直接 dp 即可。
时间复杂度为 (Theta(d^3+dw)) 。
Code
#include <bits/stdc++.h>
using namespace std;
#define Int register int
#define mod 1000000007
#define MAXN 1005
template <typename T> inline void read (T &t){t = 0;char c = getchar();int f = 1;while (c < '0' || c > '9'){if (c == '-') f = -f;c = getchar();}while (c >= '0' && c <= '9'){t = (t << 3) + (t << 1) + c - '0';c = getchar();} t *= f;}
template <typename T,typename ... Args> inline void read (T &t,Args&... args){read (t);read (args...);}
template <typename T> inline void write (T x){if (x < 0){x = -x;putchar ('-');}if (x > 9) write (x / 10);putchar (x % 10 + '0');}
int k,n,p[MAXN],a[MAXN],f[MAXN];
int mul (int a,int b){return 1ll * a * b % mod;}
int dec (int a,int b){return a >= b ? a - b : a + mod - b;}
int add (int a,int b){return a + b >= mod ? a + b - mod : a + b;}
int qkpow (int a,int b){
if (b < 0) b += mod - 1;
int res = 1;for (;b;b >>= 1,a = mul (a,a)) if (b & 1) res = mul (res,a);
return res;
}
int inv (int x){return qkpow (x,mod - 2);}
int y[MAXN],mat[MAXN][MAXN];
void Gauss (){
int up = k + 1;
for (Int i = 1;i <= up;++ i){
for (Int j = 1;j <= up;++ j) mat[i][j] = qkpow (i,j);
for (Int j = 1;j <= i;++ j) mat[i][up + 1] = add (mat[i][up + 1],qkpow (j,k));
}
for (Int i = 1;i <= up;++ i){
int pos = i;
for (Int j = i + 1;j <= up;++ j) if (mat[j][i] > mat[pos][i]) pos = j;
if (pos ^ i) swap (mat[i],mat[pos]);
for (Int j = i + 1;j <= up;++ j){
int det = mul (mat[j][i],inv (mat[i][i]));
for (Int k1 = i;k1 <= up + 1;++ k1) mat[j][k1] = dec (mat[j][k1],mul (det,mat[i][k1]));
}
}
for (Int i = up;i >= 1;-- i){
for (Int j = up;j > i;-- j) mat[i][up + 1] = dec (mat[i][up + 1],mul (f[j],mat[i][j]));
f[i] = mul (mat[i][up + 1],inv (mat[i][i]));
}
}
int getans (int i,int now){
if (now > n) return 1;
return mul (dec (1,qkpow (p[now],k - i)),getans (i,now + 1));
}
signed main(){
read (k,n),Gauss ();
int get = 1;
for (Int i = 1;i <= n;++ i) read (p[i],a[i]),get = mul (get,qkpow (p[i],a[i]));
int ans = 0;for (Int i = 1;i <= k + 1;++ i) ans = add (ans,mul (f[i],mul (qkpow (get,i),getans (i,1))));
write (ans),putchar ('
');
return 0;
}