题解 一个人的数论

题目传送门

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;
}
原文地址:https://www.cnblogs.com/Dark-Romance/p/14355224.html