loj3304.「联合省选 2020 A」作业题

题目链接

怎么会有二合一题目放在压轴题qq_emoji: yun

前半部分直接欧拉反演,没啥营养:

T(i=1n1wei)gcd(we1,,wen1)

=T(i=1n1wei)dwe1dwen1φ(d)

=d=1maxnφ(d)T,dwe1,,dwen1i=1n1wei

然后显然是要 MatrixTree 定理,但是普通的矩阵树都是求 Tvali,而不能求 Tvali

有一个经典 trick:我们把每条边变成一次多项式 wi+1 ,然后按照正常的方式求行列式,得到的一次项系数就是答案。这是因为每个乘出一次的部分都相当于钦定了选一条边,其他边任意选的方案。

然后就没了。

#include<iostream>
#include<cstdio>
using namespace std;
#define int long long
const int mod=998244353;
inline int pw(int a,int b)
{
    int res=1;
    while(b)
    {
        if(b&1)
            res=res*a%mod;
        b>>=1;
        a=a*a%mod;
    }
    return res;
}
struct edge
{
    int x,y,w;
}e[1001];
struct cp
{
    int x,y;
    cp(int x_=0,int y_=0):
        x(x_),y(y_){}
    cp operator +(const cp &other) const
    {
        return cp((x+other.x)%mod,(y+other.y)%mod);
    }
    cp operator +=(const cp &other)
    {
        x=(x+other.x)%mod;
        y=(y+other.y)%mod;
        return *this;
    }
    cp operator -(const cp &other) const
    {
        return cp((x-other.x+mod)%mod,(y-other.y+mod)%mod);
    }
    cp operator -=(const cp &other)
    {
        x=(x-other.x+mod)%mod;
        y=(y-other.y+mod)%mod;
        return *this;
    }
    cp operator *(const cp &other) const
    {
        return cp((x*other.y%mod+y*other.x%mod)%mod,y*other.y%mod);
    }
    cp operator *=(const cp &other)
    {
        x=(x*other.y%mod+y*other.x%mod)%mod;
        y=y*other.y%mod;
        return *this;
    }
    cp operator /(const cp &other) const
    {
        return cp((x*other.y%mod-y*other.x%mod+mod)%mod*pw(other.y*other.y%mod,mod-2)%mod,y*pw(other.y,mod-2)%mod);
    }
}g[31][31];
int maxn,ans,n,m,phi[200001],cnt,p[200001],sum[200001];
bool prime[200001];
inline int read()
{
    int x=0;
    char c=getchar();
    while(c<'0'||c>'9')
        c=getchar();
    while(c>='0'&&c<='9')
    {
        x=(x<<1)+(x<<3)+(c^48);
        c=getchar();
    }
    return x;
}
inline void init()
{
    phi[1]=1;
    for(register int i=2;i<=maxn;++i)
    {
        if(!prime[i])
        {
            p[++cnt]=i;
            phi[i]=i-1;
        }
        for(register int j=1;j<=cnt&&i*p[j]<=maxn;++j)
        {
            prime[i*p[j]]=1;
            if(i%p[j]==0)
            {
                phi[i*p[j]]=p[j]*phi[i];
                break;
            }
            else
                phi[i*p[j]]=(p[j]-1)*phi[i];
        }
    }
}
inline int solve()
{
    cp ans=cp(0,1);
    bool tag=0;
    for(register int i=2;i<=n;++i)
    {
        for(register int j=i+1;j<=n;++j)
            if(!g[i][i].y&&g[j][i].y)
            {
                swap(g[i],g[j]);
                tag^=1;
                break;
            }
        ans*=g[i][i];
        cp d=cp(0,1)/g[i][i];
        for(register int j=i;j<=n;++j)
            g[i][j]*=d;
        for(register int j=i+1;j<=n;++j)
        {
            d=g[j][i];
            for(register int k=i;k<=n;++k)
                g[j][k]-=g[i][k]*d;
        }
    }
    return tag? (mod-ans.x)%mod:ans.x;
}
signed main()
{
    n=read(),m=read();
    for(register int i=1;i<=m;++i)
    {
        e[i].x=read(),e[i].y=read(),maxn=max(e[i].w=read(),maxn);
        for(register int j=1;j*j<=e[i].w;++j)
            if(e[i].w%j==0)
            {
                ++sum[j];
                if(j*j!=e[i].w)
                    ++sum[e[i].w/j];
            }
    }
    init();
    for(register int d=1;d<=maxn;++d)
    {
        if(sum[d]<n-1)
            continue;
        for(register int i=1;i<=n;++i)
            for(register int j=1;j<=n;++j)
                g[i][j]=cp(0,0);
        for(register int i=1;i<=m;++i)
        {
            if(e[i].w%d)
                continue;
            g[e[i].x][e[i].x]+=cp(e[i].w,1);
            g[e[i].y][e[i].y]+=cp(e[i].w,1);
            g[e[i].x][e[i].y]-=cp(e[i].w,1);
            g[e[i].y][e[i].x]-=cp(e[i].w,1);
        }
        ans=(ans+phi[d]*solve()%mod)%mod;
    }
    printf("%lld\n",ans);
    return 0;
}
posted @   绝顶我为峰  阅读(93)  评论(0编辑  收藏  举报
编辑推荐:
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· .NET Core 中如何实现缓存的预热?
· 三行代码完成国际化适配,妙~啊~
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
点击右上角即可分享
微信分享提示