于神之怒 (今天第一个没看题解的题...)

确实今天第一个没看题解的题...

而且一开始打的是log筛,cogs上过了,大视野过不了

然后打线性筛,为了不当孙子,坚持不看题解,竟然蒙对了

$$ ans=\sum_{i=1}^n\sum_{j=1}^m gcd(i,j) $$

$$ ans=\sum_{i=1}^{min(n,m)}i^k\sum_{i|d}\mu(\frac{d}{i})\lfloor\frac{n}{d}\rfloor\lfloor\frac{m}{d}\rfloor $$

$$ ans=\sum_{d=1}^{min(n,m)}\lfloor\frac{n}{d}\rfloor\lfloor\frac{m}{d}\rfloor\sum_{i|d}\mu(\frac{i}{d})d^k $$

并不知道狄利克雷卷积是什么东西

然后就打了log筛

线性筛:

1.i是质数,$F_i=i^k-1$

2.i与prime[j]互质 $F_{i*prime[j]}=F_i*F_{prime[j]}$

3.i与prime[j]不互质 $F_{i*prime[j]}=F_i*prime[j]^k$

因为当d|i,d不包含prime[j]时,$\mu(\frac{i*prime[j]}{d})=0$,无贡献

而当有因数的时候,直接乘上 贡献即可

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#define ll long long
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;
inline int read()
{
    char q=getchar();int ans=0;
    while(q<'0'||q>'9')q=getchar();
    while(q>='0'&&q<='9'){ans=ans*10+q-'0';q=getchar();}
    return ans;
}
const int mod=1000000007;
const int N=5000006;

ll qpow(ll a,int ci)
{
    ll ans=1;
    while(ci)
    {
        if(ci&1)
            ans=ans*a%mod;
        a=a*a%mod;
        ci>>=1;
    }
    return ans;
}

int T,K,n,m;
ll mi[N];
int prime[N],cnt;
bool he[N];
int mu[N];
ll ji[N];

void chu()
{
    for(int i=0;i<N;++i)
      mi[i]=qpow(i,K)%mod;
    mu[1]=1;ji[1]=1;
    for(int i=2;i<N;++i)
    {
        if(!he[i])
        {
            prime[++cnt]=i;
            mu[i]=-1;
            ji[i]=mi[i]-1;
        }
        for(int j=1;j<=cnt&&prime[j]*i<N;++j)
        {
            he[i*prime[j]]=1;
            if(i%prime[j]==0)
            {
                mu[i*prime[j]]=0;
                ji[i*prime[j]]=mi[prime[j]]*ji[i]%mod;
                break;
            }
            mu[i*prime[j]]=-mu[i];
            ji[i*prime[j]]=ji[i]*ji[prime[j]]%mod;
        }
    }
    
    for(int i=1;i<N;++i)
        ji[i]+=ji[i-1],ji[i]%=mod;
}

ll work()
{
    if(n>m)
        swap(n,m);
    ll ans=0;
    int nx;
    for(int i=1;i<=n;i=nx+1)
    {
        nx=min( n/(n/i),m/(m/i) );
        ans+=(ll)(n/i)*(m/i)%mod*(ji[nx]-ji[i-1]+mod)%mod;
        ans%=mod;
    }
    return (ans+mod)%mod;
}

int main(){
    
    //freopen("bzoj_44074.in","r",stdin);
    //freopen("bzoj_4407.out","w",stdout);
    //freopen("out.out","w",stdout);
    
    T=read();K=read();
    chu();
    while(T--)
    {
        n=read();m=read();
        printf("%lld\n",work());
    }
}
AA

 

posted @ 2017-10-16 12:07  A_LEAF  阅读(105)  评论(0编辑  收藏  举报