题目大意
现在定义路径上所有边权的最大公约数定义为一条路径的值。
现在给定一个
N
个点
N≤100
M≤50000
T≤500
路径的权值≤100
解题思路
我们可以用莫比乌斯来做这题,设
Fi
为边权为
i
的倍数的路径的数量,最后答案就是
我们知道一个数的约数最多就只有根号个,而且这题的边权最大只有100,那么考虑建100幅图,在第
程序
//YxuanwKeith
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std;
const int MAXN = 105, MAXM = 5e4 + 5;
const int Mo = 1e9 + 7;
struct Node {
int u, v, w;
} Q[MAXM];
bool Flag[MAXN];
int N, M, Mu[MAXN], Fac[MAXN];
int tot[MAXN], Ans[MAXN];
struct Solve {
int Map[MAXN][MAXN], Num[MAXN], Ord[MAXN], F[MAXN], Ans;
void Get() {
for (int i = 1; i <= N; i ++)
for (int j = 1; j <= N; j ++)
Num[j] += Map[i][j];
static int D[MAXN];
int top = 0, p = 0;
for (int i = 1; i <= N; i ++)
if (!Num[i]) D[++ top] = i;
while (top) {
int Now = D[top --];
Ord[++ p] = Now;
for (int i = 1; i <= N; i ++)
if (Map[Now][i]) {
Num[i] -= Map[Now][i];
if (!Num[i]) D[++ top] = i;
}
}
Ans = 0;
for (; p; p --) {
int Now = Ord[p];
F[Now] = 1;
for (int i = 1; i <= N; i ++)
F[Now] = (F[Now] + Map[Now][i] * 1ll * F[i] % Mo) % Mo;
Ans = (Ans + F[Now] - 1) % Mo;
}
}
} P[MAXN];
int Prep() {
Mu[1] = 1;
for (int i = 2; i < MAXN; i ++) {
if (!Flag[i]) {
Mu[i] = -1;
Fac[++ Fac[0]] = i;
}
for (int j = 1; j <= Fac[0]; j ++) {
if (1ll * i * Fac[j] >= MAXN) break;
Flag[i * Fac[j]] = 1;
if (i % Fac[j]) Mu[i * Fac[j]] = -Mu[i]; else {
Mu[i * Fac[j]] = 0;
break;
}
}
}
}
int main() {
scanf("%d%d", &N, &M);
Prep();
for (int i = 1; i <= M; i ++)
scanf("%d%d%d", &Q[i].u, &Q[i].v, &Q[i].w);
for (int i = 1; i <= M; i ++)
for (int j = 1; j <= Q[i].w; j ++)
if (Q[i].w % j == 0 && Mu[j] != 0) P[j].Map[Q[i].u][Q[i].v] ++;
int Ans = 0;
for (int i = 1; i < MAXN; i ++)
if (Mu[i] != 0) {
P[i].Get();
Ans = ((Ans + P[i].Ans * 1ll * Mu[i]) % Mo + Mo) % Mo;
}
printf("%d\n", Ans);
int C;
scanf("%d\n", &C);
for (int i = 1; i <= C; i ++) {
int Ord, Val;
scanf("%d%d", &Ord, &Val);
memset(Flag, 0, sizeof Flag);
for (int j = 1; j <= Q[Ord].w; j ++)
if (Q[Ord].w % j == 0 && Mu[j]) {
P[j].Map[Q[Ord].u][Q[Ord].v] --;
Flag[j] = 1;
}
Q[Ord].w = Val;
for (int j = 1; j <= Q[Ord].w; j ++)
if (Q[Ord].w % j == 0 && Mu[j]) {
P[j].Map[Q[Ord].u][Q[Ord].v] ++;
Flag[j] = 1;
}
for (int j = 1; j < MAXN; j ++)
if (Mu[j] && Flag[j]) P[j].Get();
Ans = 0;
for (int j= 1; j < MAXN; j ++)
if (Mu[j]) Ans = ((Ans + P[j].Ans * Mu[j]) % Mo + Mo) % Mo;
printf("%d\n", Ans);
}
}