题解 P6624 【[2020 年联考 A 卷] 作业题】
对于枚举的每个
不过珂以优化,只对可选边数大于等于
注:这个
code:
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
const int mod=998244353;
#define N 33
#define M 200020
inline int read(){
int x=0,f=1;
char c=getchar();
while(c<'0'||c>'9'){
if(c=='-')f=-1;
c=getchar();
}
while(c>='0'&&c<='9'){
x=(x<<1)+(x<<3)+c-'0';
c=getchar();
}
return x*f;
}
typedef pair<int,int> pii;
int n,m,ans,h[M];
int qpow(int a,int b){
int ans=1;
while(b){
if(b&1)ans=1LL*ans*a%mod;
a=1LL*a*a%mod;
b>>=1;
}
return ans;
}
pii g[N][N]; //(常数项系数,一次项系数)
pii operator +(const pii a,const pii b){
return make_pair((a.first+b.first)%mod,(a.second+b.second)%mod);
}
pii operator -(const pii a,const pii b){
return make_pair((a.first-b.first+mod)%mod,(a.second-b.second+mod)%mod);
}
pii operator *(const pii a,const pii b){
return make_pair(1LL*a.first*b.first%mod,(1LL*a.first*b.second+1LL*a.second*b.first)%mod);
}
pii operator /(const pii a,const pii b){
int inv=qpow(b.first,mod-2);
return make_pair(1LL*a.first*inv%mod,(1LL*a.second*b.first%mod-1LL*a.first*b.second%mod+mod)%mod*inv%mod*inv%mod);
}
int x[N*N],y[N*N],w[N*N],mx;
int p[M],pn,phi[M];
bool ntp[M];
void init(int n){
phi[1]=ntp[1]=1;
for(int i=2;i<=n;++i){
if(!ntp[i])p[++pn]=i,phi[i]=i-1;
for(int j=1;j<=pn&&p[j]*i<=n;++j){
ntp[p[j]*i]=true;
if(i%p[j]==0){
phi[p[j]*i]=phi[i]*p[j];
break;
}
phi[p[j]*i]=phi[i]*(p[j]-1);
}
}
}
pii Guass(int n){
pii ans=make_pair(1,0);
bool rev=false;
for(int i=1;i<=n;++i){
if(!g[i][i].first){
for(int j=i+1;j<=n;++j){
if(g[j][i].first){
rev^=1;
swap(g[i],g[j]);
break;
}
}
}
pii inv=make_pair(1,0)/g[i][i];
for(int j=i+1;j<=n;++j){
pii div=g[j][i]*inv;
for(int k=i;k<=n;++k){
g[j][k]=g[j][k]-div*g[i][k];
}
}
ans=ans*g[i][i];
}
return rev?make_pair(0,0)-ans:ans;
}
int Solve(int t){
memset(g,0,sizeof(g));
for(int i=1;i<=m;++i){
if(w[i]%t)continue;
g[x[i]][x[i]]=g[x[i]][x[i]]+make_pair(1,w[i]);
g[y[i]][y[i]]=g[y[i]][y[i]]+make_pair(1,w[i]);
g[x[i]][y[i]]=g[x[i]][y[i]]-make_pair(1,w[i]);
g[y[i]][x[i]]=g[y[i]][x[i]]-make_pair(1,w[i]);
}
return Guass(n-1).second;
}
void check(int x){
for(int i=1;i*i<=x;++i){
if(x%i==0){
++h[i];
if(i*i!=x)++h[x/i];
}
}
}
int main(){
freopen("count.in","r",stdin);
freopen("count.out","w",stdout);
n=read(),m=read();
for(int i=1;i<=m;++i){
x[i]=read(),y[i]=read(),w[i]=read();
check(w[i]);
mx=max(mx,w[i]);
}
init(mx);
for(int i=1;i<=mx;++i){
if(h[i]<n-1)continue;
ans=(ans+1LL*phi[i]*Solve(i))%mod;
}
cout<<ans<<endl;
return 0;
}
Froggy's blog