bzoj3601: 一個人的數論 莫比烏斯反演 高斯消元
阿新 • • 發佈:2018-12-12
題目
分析
數論神仙題,話不多說開始推導
結論:等冪和
也就是次等冪和是關於的次多項式,可以採用高斯消元搞出這個玩意兒。(推導?插值啊!!)
令
顯然這玩意兒是個積性函式,因為他本身是兩個積性函式的狄利克雷卷積。
所以我們只需要研究,然後乘起來。
當且僅當時
所以有
呼呼,解決了!!
程式碼
#include<cstdio>
#include<algorithm>
const int P = 1e9 + 7, N = 1e3 + 10;
int ri() {
char c = getchar(); int x = 0; for(;c < '0' || c > '9'; c = getchar()) ;
for(;c >= '0' && c <= '9'; c = getchar()) x = (x << 1) + (x << 3) - '0' + c; return x;
}
int a[N][N], p[N], q[N], d, w;
int Pow(int x, int k) {
k < 0 ? k += P - 1 : 0; int r = 1;
for(;k; x = 1LL * x * x % P, k >>= 1) if(k & 1) r = 1LL * r * x % P;
return r;
}
void Gas() {
for(int i = 0;i <= d + 1; ++i) {
a[i][0] = 1;
for(int j = 1;j <= d + 1; ++j) a[i][j] = 1LL * a[i][j - 1] * (i + 1) % P;
if(i) a[i][d + 2] = a[i - 1][d + 2];
a[i][d + 2] = (a[i][d + 2] + a[i][d]) % P;
}
for(int i = 0, j; i <= d + 1; ++i) {
for(j = i; j <= d + 1; ++j) if(a[j][i]) break;
if(i != j) std::swap(a[i], a[j]);
for(j = i + 1; j <= d + 1; ++j) {
int t = 1LL * a[j][i] * Pow(a[i][i], P - 2) % P;
for(int k = i; k <= d + 2; ++k)
a[j][k] = (a[j][k] + P - 1LL * a[i][k] * t % P) % P;
}
}
for(int i = d + 1; ~i; --i) {
for(int j = i + 1; j <= d + 1; ++j)
a[i][d + 2] = (a[i][d + 2] + P - 1LL * a[i][j] * a[j][d + 2] % P) % P;
a[i][d + 2] = 1LL * a[i][d + 2] * Pow(a[i][i], P - 2) % P;
}
}
int main() {
d = ri(); w = ri(); Gas(); int ans = 0;
for(int i = 1;i <= w; ++i) p[i] = ri(), q[i] = ri();
for(int i = 0, r = 1; i <= d + 1; ans = (ans + 1LL * a[i++][d + 2] * r) % P, r = 1)
for(int j = 1;j <= w; ++j)
r = 1LL * r * Pow(p[j], 1LL * q[j] * i % (P - 1)) % P * (1 + P - Pow(p[j], d - i)) % P;
printf("%d\n", ans);
return 0;
}