bzoj2693: jzptab

最终的柿子:sigema(min)T K(T)*S(T)

K(T)=sigema(n/T)i sigema(m/T)j i*j

S(T)=sigema(d|T)u(d)*d^d*T

收获:写柿子的时候不能省掉范围。。。要分块找向下整除

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std;
typedef long long LL;
const LL mod=100000009;
LL MOD(LL x){return (x%mod+mod)%mod;}
LL sqr(LL x){return x*x%mod;}

LL n,m;
int pr;LL prime[10000010]; bool v[10000010];
LL S[10000010];
LL getK(LL x){return ((n/x+1)*(n/x)/2%mod)*((m/x+1)*(m/x)/2%mod)%mod;}
void get_prime(int li)
{
    pr=0;
    S[1]=1;
    for(LL i=2;i<=li;i++)
    {
        if(v[i]==false)
        {
            prime[++pr]=i;
            S[i]=1-i;
        }
        for(int j=1;j<=pr&&i*prime[j]<=li;j++)
        {
            v[i*prime[j]]=true;
            if(i%prime[j]==0)
            {
                S[i*prime[j]]=S[i];
                break;
            }
            S[i*prime[j]]=MOD(S[i]-S[i]*prime[j]%mod);
        }
        S[i]=(S[i]*i%mod+S[i-1])%mod;
    }
}

int main()
{
//    freopen("a.in","r",stdin);
//    freopen("a.out","w",stdout);
    get_prime(10000000);
    int T;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%lld%lld",&n,&m);LL li=min(n,m);
        LL ans=0,last;
        for(LL i=1;i<=li;i=last+1)
        {
            last=min(n/(n/i),m/(m/i));
            ans=(ans+MOD(S[last]-S[i-1])*getK(i)%mod)%mod;
        }
        printf("%lld\n",(ans+mod)%mod);
    }
    
    return 0;
}

 

posted @ 2019-01-02 16:12  AKCqhzdy  阅读(123)  评论(0编辑  收藏  举报