[SDOI2018] 旧试题(没过,差的远)

出题人“不优秀的三元环枚举也可以通过”
然而我不计算答案只枚举三元环就跑了半分钟……
觉得如果真的去卡一波或许能过吧或许XD
代码:

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<unordered_map>
#include<assert.h>
#define mod 1000000007
#define gc getchar()
#define N 600010
#define M 12000010
#define hv(x,y) ((lint)(x)*N+(y))
#define lint long long
#define pb push_back
#define debug(x) cerr<<#x<<"="<<x
#define sp <<" "
#define ln <<endl
using namespace std;
inline int inn()
{
    int x,ch;while((ch=gc)<'0'||ch>'9');
    x=ch^'0';while((ch=gc)>='0'&&ch<='9')
        x=(x<<1)+(x<<3)+(ch^'0');return x;
}
int u[M],v[M],ec,pri[N],mu[N],f[N],P[N],Q[N],R[N],ans[5];
bool notp[N],vis[N];vector<int> in[N],d[N];int val[N],A[5];
unordered_map<lint,int> m;int cnt,du[N],lis[N],b[N],bel[N];
inline int inv(int x,int k=mod-2,int ans=1)
{   for(;k;k>>=1,x=(lint)x*x%mod) (k&1)?ans=(lint)ans*x%mod:0;return ans;   }
inline int add_edge(int x,int y,int z)
{   return ec++,u[ec]=x,v[ec]=y,x[du]++,y[du]++,in[y].pb(x),m.insert(make_pair(hv(x,y),z)),0;   }
inline int sol(int x,int s) { return (!s)?0:((s>0)?x:(mod-x)%mod); }
inline int F(int x,int y)
{
    int bx=bel[x],by=bel[y];if(bx>by) swap(bx,by);
    return f[A[(!bx)?(by==1?0:2):1]/m[hv(x,y)]];
}

inline int gcd(int x,int y) { return x?gcd(y%x,x):y; }
inline lint lcm(int x,int y) { return (lint)x*y/gcd(x,y); }
inline int mol(lint x) { return x%=mod,(x<0)?x+mod:x; }
lint p[5];

int main()
{
    mu[1]=1;int n=100000;
    for(int i=2;i<=n;i++)
    {
        if(!notp[i]) pri[++cnt]=i,mu[i]=-1;
        for(int j=1;j<=cnt;j++)
        {
            if((lint)pri[j]*i>n) break;
            int x=pri[j]*i;notp[x]=true;
            if(i%pri[j]) mu[x]=-mu[i];
            else { mu[x]=0;break; }
        }
    }
    for(int i=1;i<=n;i++)
        for(int j=i;j<=n;j+=i) d[j].push_back(i);
    for(int i=1;i<=n;i++)
        for(int s=1,t;s<=i;s=t+1)
            t=i/(i/s),(f[i]+=(t-s+1ll)*(i/s)%mod)%=mod;
//  for(int i=1;i<=30;i++) debug(i)sp,debug(mu[i])sp,debug(f[i])ln;
    for(int T=inn();T;T--)
    {
        int nc=0,t=0;ans[0]=ans[1]=ans[2]=ans[3]=0;
        A[0]=inn(),A[1]=inn(),A[2]=inn(),sort(A,A+3),swap(A[0],A[2]);

/*      int Ans=0;
        for(int i=1;i<=A[0];i++)
            for(int j=1;j<=A[0];j++)
                for(int k=1;k<=A[0];k++)
                    (Ans+=sol((lint)f[A[0]/lcm(i,j)]*f[A[1]/lcm(i,k)]%mod*f[A[2]/lcm(j,k)]%mod,mu[i]*mu[j]*mu[k]))%=mod;
        debug(Ans)ln;*/

        for(int i=1;i<=A[0];i++) if(mu[i]) val[P[i]=++nc]=i,bel[nc]=0;
        for(int i=1;i<=A[0];i++) if(mu[i]) val[Q[i]=++nc]=i,bel[nc]=1;
        for(int i=1;i<=A[0];i++) if(mu[i]) val[R[i]=++nc]=i,bel[nc]=2;
        memset(du,0,sizeof(int)*(nc+1)),m.clear(),ec=0;
        for(int i=1;i<=nc;i++) in[i].clear();
        for(int i=1;i<=nc/3;i++)
        {
            int x=val[i];t=0;
            for(int j=(int)d[x].size()-1;j>=0;j--)
                for(int k=d[x][j];k<=(lint)A[0]*d[x][j]/x;k+=d[x][j])
                    if(mu[k]&&!vis[k])
                    {
                        int w=(int)((lint)k*x/d[x][j]);vis[lis[++t]=k]=true;
                        add_edge(P[x],Q[k],w),add_edge(Q[x],R[k],w),add_edge(R[x],P[k],w);
                    }
            for(int j=1;j<=t;j++) vis[lis[j]]=false;
        }
        int s=max(1,(int)sqrt(ec/3+0.5)),bc=0;
        for(int i=1;i<=nc;i++) if(i[du]>s) b[++bc]=i;
        for(int i=1;i<=bc;i++) if(bel[b[i]]==0)
            for(int j=1;j<=bc;j++) if(bel[b[j]]==1)
                if(m.count(hv(b[i],b[j])))
                {
                    lint p3B=0ll;int x=b[i][val],y=b[j][val];
                    for(int k=1;k<=bc;k++)
                        if(m.count(hv(b[j],b[k]))&&m.count(hv(b[k],b[i]))) if(bel[b[k]]==2)
                            p3B+=sol((lint)F(b[j],b[k])*F(b[k],b[i])%mod,mu[x]*mu[y]*mu[b[k][val]]);
                    (ans[0]+=p3B%mod*F(b[i],b[j])%mod)%=mod;
                }
        for(int i=1;i<=ec;i++) if(u[i][du]<=s)
        {
            p[1]=p[2]=p[3]=0ll;
            for(int j=0,x=u[i],y=v[i],z;j<(int)in[x].size();j++)
            {
                if(!m.count(hv(y,z=in[x][j]))) continue;
                int sgn=mu[x[val]]*mu[y[val]]*mu[z[val]];
                int ds=(x[du]<=s)+(y[du]<=s)+(z[du]<=s);
                p[ds]=mol(p[ds]+sgn*(lint)F(y,z)*F(z,x));
            }
            int w=F(u[i],v[i]);
            ans[1]=mol(ans[1]+p[1]%mod*w);
            ans[2]=mol(ans[2]+p[2]%mod*w);
            ans[3]=mol(ans[3]+p[3]%mod*w);
        }
        printf("%lld\n",((lint)ans[3]*inv(3)+(lint)ans[2]*inv(2)+ans[1]+ans[0])%mod);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/mys_c_k/article/details/80421855