Description

路径上所有边权的最大公约数定义为一条路径的值。
给定一个有向无环图。
T次修改操作,每次修改一条边的边权,每次修改后输出有向无环图上路径的值为1的路径数量(对1,000,000,007取模)。

Solution

我们看到gcd=1的这个东西,一定要想想容斥可不可以(1的倍数的个数-2的倍数的个数-3的倍数的个数-5的倍数的个数……这个可以直接用莫比乌斯函数来搞)。
设f[i]表示值为i的倍数的路径数,那么答案就等于∑100i=1μ(i)∗f[i]
我们针对一下式子,关键就是要怎么去求值i的倍数的路径书。
我们知道如果有很多个数,都是i的倍数,那么他们的gcd肯定是i的倍数。
所以对于一个i,建一个图,把所有边权是i的倍数的放入这个图中,然后求出来的答案就是i的倍数的路径数及f[i](用容斥求),最多只用开100个图。
然后每次修改的时候,求用根号的时间来重构一下这个图。
时间复杂度一共是O(T∗n√∗m)

Code

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<math.h>
#define fo(i,a,b) for(i=a;i<=b;i++)
#define rep(i,a) for(i=first[a];i;i=next[i])
using namespace std;
typedef long long ll;
const int maxn=5e4+7,mo=1e9+7;
int i,j,k,l,t,n,m;
int p[107],q;
int a[maxn],b[maxn],c[maxn],d[maxn];
bool bz[107];
ll ans,miu[107];
struct node{
int b[107],tuo[107];
ll c[107],sum,a[107][107];
void qiu(){
int i,j;
fo(i,1,n)fo(j,1,n)b[j]+=a[i][j];
d[0]=tuo[0]=0;
fo(i,1,n)if(!b[i])d[++d[0]]=i;
while(d[0]){
j=d[d[0]--];
tuo[++tuo[0]]=j;
fo(i,1,n){
if(a[j][i]){
b[i]-=a[j][i];
if(!b[i])d[++d[0]]=i;
}
}
}
sum=0;
while(tuo[0]){
i=tuo[tuo[0]--];
c[i]=0;b[i]=0;
fo(j,1,n){
c[i]=c[i]+a[i][j]*c[j];
if(c[i]>mo)c[i]%=mo;
}
sum=sum+c[i];
if(sum>mo)sum-=mo;
c[i]++;
}
}
}e[107];
int main(){
freopen("fan.in","r",stdin);
freopen("fan.out","w",stdout);
miu[1]=1;
fo(i,2,100){
if(!bz[i])p[++p[0]]=i,miu[i]=-1;
fo(j,1,p[0]){
t=p[j]*i;
if(t>100)break;bz[t]=1;
if(i%p[j]==0)break;
miu[t]=-miu[i];
}
}
scanf("%d%d",&n,&m);
fo(i,1,m)scanf("%d%d%d",&a[i],&b[i],&c[i]);
fo(i,1,100)fo(j,1,m)if(c[j]%i==0&&miu[i]!=0)e[i].a[a[j]][b[j]]++;
fo(i,1,100){
if(!miu[i])continue;
e[i].qiu();
ans=ans+e[i].sum*miu[i];
if(ans>mo)ans-=mo;
if(ans<mo)ans+=mo;
}
ans=(ans+mo)%mo;
printf("%lld\n",ans);
scanf("%d",&q);
while(q--){
scanf("%d%d",&k,&t);l=c[k];
fo(i,1,sqrt(l)){
if(l%i==0){
if(miu[i]!=0){
e[i].qiu();
ans=ans-e[i].sum*miu[i];
e[i].a[a[k]][b[k]]--;
e[i].qiu();
ans=ans+e[i].sum*miu[i];
}
if(i*i==l)break;
if(miu[l/i]!=0){
e[l/i].qiu();
ans=ans-e[l/i].sum*miu[l/i];
e[l/i].a[a[k]][b[k]]--;
e[l/i].qiu();
ans=ans+e[l/i].sum*miu[l/i];
}
}
}
c[k]=t;
fo(i,1,sqrt(t)){
if(t%i==0){
if(miu[i]!=0){
e[i].qiu();
ans=ans-e[i].sum*miu[i];
e[i].a[a[k]][b[k]]++;
e[i].qiu();
ans=ans+e[i].sum*miu[i];
}
if(i*i==t)break;
if(miu[t/i]!=0){
e[t/i].qiu();
ans=ans-e[t/i].sum*miu[t/i];
e[t/i].a[a[k]][b[k]]++;
e[t/i].qiu();
ans=ans+e[t/i].sum*miu[t/i];
}
}
}
ans=(ans%mo+mo)%mo;
printf("%lld\n",ans);
}
}