• SDOI2018 旧试题


    题目大意:

    题解:
    大毒瘤。

    先反演:

    然后套路处理后面那三坨为fa,fb,fc。

    为了速度,我们可以直接枚举lcm,将μi!=0&&μj!=0之间建一条边权为lcm(i,j)的边。

    如果(u,v,w)这个三元组合法的话:

    • 三者互不相同。此时应形成一个三元环。
    • 两项相同。此时有一条边即可。
    • 三项相同。此时枚举所有的点即可。

    代码:

    #include<vector>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    #define N 100050
    #define MOD 1000000007
    #define ll long long
    ll pri[N],cnt,mu[N],ft[N][10],mem[N],T,a,b,c;
    bool vis[N];
    ll fa[N],fb[N],fc[N];
    void init()
    {
        mu[1]=1;
        for(register ll i=2;i<=100000;i++)
        {
            if(!vis[i])
            {
                mu[i]=-1;
                pri[++cnt]=i;
            }
            for(register ll j=1;i*pri[j]<=100000;j++)
            {
                vis[i*pri[j]]=1;
                if(i%pri[j])mu[i*pri[j]]=-mu[i];
                else break;
            }
        }
        for(register ll i=1;i<=cnt;i++)
        {
            for(register ll j=1;j*pri[i]<=100000;j++)
            {
                mem[pri[i]*j]++;
                ft[pri[i]*j][mem[pri[i]*j]]=pri[i];
            }
        }
    }
    struct Pair
    {
        ll x,v;
        Pair(){}
        Pair(ll x,ll v):x(x),v(v){};
    };
    vector<Pair>ve[N];
    ll d[N];
    void initt()
    {
        for(register ll i=1;i<=a;i++)fa[i]=0;
        for(register ll i=1;i<=b;i++)fb[i]=0;
        for(register ll i=1;i<=c;i++)fc[i]=0;
        for(register ll i=1;i<=c;i++)
        {
            vector<Pair>tmp;
            swap(ve[i],tmp);
            d[i]=0;
        }
    }
    ll hs[N];
    struct EG
    {
        ll f,t,v;
    }e[10*N];
    ll sol()
    {
        if(a>b)swap(a,b);
        if(a>c)swap(a,c);
        if(b>c)swap(b,c);
        for(register ll i=1;i<=a;i++)
            for(register ll j=1;i*j<=a;j++)
            {
                fa[i]+=(a/(i*j));
                if(fa[i]>MOD)fa[i]-=MOD;
            }
        for(register ll i=1;i<=b;i++)
            for(register ll j=1;i*j<=b;j++)
            {
                fb[i]+=(b/(i*j));
                if(fb[i]>MOD)fb[i]-=MOD;
            }
        for(register ll i=1;i<=c;i++)
            for(register ll j=1;i*j<=c;j++)
            {
                fc[i]+=(c/(i*j));
                if(fc[i]>MOD)fc[i]-=MOD;
            }
        ll ct=0;
        for(register ll i=1;i<=c;i++)//lcm
        {
            if(!mu[i])continue;
            for(register ll j=0;j<(1<<mem[i]);j++)
            {
                ll u = 1;
                for(register ll k=1;k<=mem[i];k++)
                    if((j>>(k-1))&1)
                        u*=ft[i][k];
                for(register ll k = j;;k=(k-1)&j)
                {
                    ll v = i/u;
                    for(register ll w=1;w<=mem[i];w++)
                        if((k>>(w-1))&1)
                            v*=ft[i][w];
                    if(u>v)
                    {
                        d[u]++,d[v]++,ct++;
                        e[ct].f=u,e[ct].t=v,e[ct].v=i;
                    }
                    if(!k)break;
                }
            }
        }
        for(register ll i=1;i<=ct;i++)
        {
            if(d[e[i].f]<d[e[i].t])
                swap(e[i].f,e[i].t);
            ve[e[i].f].push_back(Pair(e[i].t,e[i].v));
        }
        ll ret = 0;
        ll p1,p2,p3,v1,v2,v3,kk;
        for(register ll i=1;i<=b;i++)
        {
            if(!mu[i])continue;
            //abc
            for(register ll j=0;j<ve[i].size();j++)
                hs[ve[i][j].x]=ve[i][j].v;
            for(register ll j=0;j<ve[i].size();j++)
            {
                for(register ll k=0;k<ve[ve[i][j].x].size();k++)
                {
                    if(hs[ve[ve[i][j].x][k].x]&&ve[i][j].x!=ve[ve[i][j].x][k].x)
                    {
                        p1=i,p2=ve[i][j].x,p3=ve[p2][k].x;
                        v1 = ve[p1][j].v;v2 = ve[p2][k].v;v3 = hs[p3];
                        kk = mu[p1]*mu[p2]*mu[p3];
                        ret = (ret+kk*fa[v1]*fb[v2]*fc[v3])%MOD;
                        ret = (ret+kk*fa[v1]*fb[v3]*fc[v2])%MOD;
                        ret = (ret+kk*fa[v2]*fb[v1]*fc[v3])%MOD;
                        if(ret<0)ret+=MOD;
                        ret = (ret+kk*fa[v2]*fb[v3]*fc[v1])%MOD;
                        ret = (ret+kk*fa[v3]*fb[v1]*fc[v2])%MOD;
                        ret = (ret+kk*fa[v3]*fb[v2]*fc[v1])%MOD;
                        if(ret<0)ret+=MOD;
                    }
                }
            }
            for(register ll j=0;j<ve[i].size();j++)
                hs[ve[i][j].x]=0;
            //aab abb
            for(register ll j=0;j<ve[i].size();j++)
            {
                ll to = ve[i][j].x;
                kk=mu[i];
                p1=i,p2=to,p3=p2;
                v1 = ve[p1][j].v;v2 = p2;v3 = v1;
                ret = (ret+kk*fa[v3]*fb[v1]*fc[v2])%MOD;
                ret = (ret+kk*fa[v2]*fb[v3]*fc[v1])%MOD;
                ret = (ret+kk*fa[v1]*fb[v2]*fc[v3])%MOD;
                if(ret<0)ret+=MOD;
                kk=mu[to];
                p1=i,p2=to,p3=p1;
                v1 = ve[p1][j].v;v2 = v1;v3 = p1;
                ret = (ret+kk*fa[v3]*fb[v1]*fc[v2])%MOD;
                ret = (ret+kk*fa[v2]*fb[v3]*fc[v1])%MOD;
                ret = (ret+kk*fa[v1]*fb[v2]*fc[v3])%MOD;
                if(ret<0)ret+=MOD;
            }
            //aaa
            ret = (ret+mu[i]*fa[i]*fb[i]*fc[i])%MOD;
            if(ret<0)ret+=MOD;
        }
        return ret;
    }
    int main()
    {
        init();
        scanf("%lld",&T);
        while(T--)
        {
            scanf("%lld%lld%lld",&a,&b,&c);
            printf("%lld
    ",sol());
            initt();
        }
        return 0;
    }
  • 相关阅读:
    pyqt的常用知识点记录
    Ansys采用后处理list Rusult输出位移时负号原因导致不能分列的python解决方法
    matlab调用ANSYS进行分析
    Matlab采用load加载txt文件时显示:错误使用load,无法打开要输出的文件
    Matlab绘制单元,云图
    关于chol分解的置换向量的问题及正定对称稀疏矩阵的构造
    Pr中字幕模糊的问题
    Matlab中文乱码问题
    Qt信号与槽---基于vs2013+qt5
    Microsoft To Do-安卓-Windows-Mac
  • 原文地址:https://www.cnblogs.com/LiGuanlin1124/p/10078791.html
Copyright © 2020-2023  润新知