BZOJ4407: 于神之怒加强版

莫比乌斯反演
发现搞出来的式子和昨天的差不多

#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
const
   int mod=1000000007;
const
   int maxn=5000001;
bool check[maxn];
int sq[maxn],prime[maxn],G[maxn],Pre[maxn],mu[maxn];
int tot;
char c;
inline void read(int &a)
{a=0;do c=getchar();while(c<'0'||c>'9');while(c<='9'&&c>='0')a=(a<<3)+(a<<1)+c-'0',c=getchar();}

int main()
{ 
    int T,tp,K,i,j,k,l; 
    read(T),read(K);
    sq[1]=1;
    for(i=2;i<maxn;i++)
       {
         tp=i;
         l=K;
         sq[i]=1;
         for(j=1;l;j<<=1,tp=(tp*1ll*tp)%mod)
               if(l&j)l^=j,sq[i]=(sq[i]*1ll*tp)%mod;    
       }
    for(i=2;i<maxn;i++)
    {
        if(!check[i])
                   G[i]=sq[i]-1,prime[++tot]=i;
        for(j=1;j<=tot;j++)
        {
             if(i*1ll*prime[j]>=maxn)break;
             check[i*prime[j]]=true;
             if(i%prime[j]==0){G[i*prime[j]]=(sq[prime[j]]*1ll*G[i])%mod;break;}
             else  G[i*prime[j]]=((sq[prime[j]]-1ll)*G[i])%mod;
        }
    }
    G[1]=1;
   for(i=1;i<maxn;i++)
      Pre[i]=(Pre[i-1]+G[i])%mod;
    int next,n,m,Div1,Div2;
    long long ans;
    while(T--)
    {
        read(n),read(m);
        if(n>m)swap(n,m);
        tp=1;
        ans=0;
        while(tp<=n)
        {
            Div1=n/tp;
            i=n/Div1+1;
            Div2=m/tp; j=m/Div2+1;
            next=min(i,j);
            ans=(ans+(Div1*1ll*Div2)%mod*((Pre[next-1]-Pre[tp-1]+mod)%mod))%mod;
            tp=next;
        }
        printf("%lld\n",ans);
    }

    return 0;
}

突然度教说只需要处理质数的p次方就好了
对啊!!

#include<iostream>
#include<cstring>
using namespace std;
const
   int mod=1000000007;
const
   int maxn=5000001;
bool check[maxn];
int sq[maxn],prime[maxn],G[maxn],Pre[maxn],mu[maxn];
int tot;
char c;
inline void read(int &a)
{a=0;do c=getchar();while(c<'0'||c>'9');while(c<='9'&&c>='0')a=(a<<3)+(a<<1)+c-'0',c=getchar();}

int main()
{ 
    int T,tp,K,i,j,k,l; 
    read(T),read(K);
    sq[1]=1;
    for(i=2;i<maxn;i++)
    {
        if(!check[i])
                  {
                    tp=i;
                    l=K;
                    sq[i]=1;
                    for(j=1;l;j<<=1,tp=(tp*1ll*tp)%mod)
                      if(l&j)l^=j,sq[i]=(sq[i]*1ll*tp)%mod;
                       G[i]=sq[i]-1,prime[++tot]=i;
                  }
        for(j=1;j<=tot;j++)
        {
             if(i*1ll*prime[j]>=maxn)break;
             check[i*prime[j]]=true;
             if(i%prime[j]==0){G[i*prime[j]]=(sq[prime[j]]*1ll*G[i])%mod;break;}
             else  G[i*prime[j]]=((sq[prime[j]]-1ll)*G[i])%mod;
        }
    }
    G[1]=1;
   for(i=1;i<maxn;i++)
      Pre[i]=(Pre[i-1]+G[i])%mod;
    int next,n,m,Div1,Div2;
    long long ans;
    while(T--)
    {
        read(n),read(m);
        if(n>m)swap(n,m);
        tp=1;
        ans=0;
        while(tp<=n)
        {
            Div1=n/tp;
            i=n/Div1+1;
            Div2=m/tp; j=m/Div2+1;
            next=min(i,j);
            ans=(ans+(Div1*1ll*Div2)%mod*((Pre[next-1]-Pre[tp-1]+mod)%mod))%mod;
            tp=next;
        }
        printf("%lld\n",ans);
    }

    return 0;
}

你可能感兴趣的:(gcd)