bzoj3309: DZY Loves Math

第三次复习反演。。。

感觉第二次学的时候还是有点用的

整理了下思路。可以去看一下我的blog

这题就是第二种类型的题。然而我不会化简K。。%PoPoQQQ

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std;
typedef long long LL;

bool v[10001000];
int pr,prime[10001000];
int K[10001000],p[10001000],a[10001000];//最后一个质因数^其次数,该质因数次数 
void get_K()
{
    memset(v,true,sizeof(v));
    v[1]=false;
    for(int i=2;i<=10000000;i++)
    {
        if(v[i]==true)
        {
            prime[++pr]=i;
            p[i]=i;
            a[i]=1;
            K[i]=1;
        }
        for(int j=1;j<=pr&&(LL(i*prime[j]))<=10000000;j++)
        {
            v[i*prime[j]]=false;
            if(i%prime[j]==0)
            {
                p[i*prime[j]]=p[i]*prime[j];
                a[i*prime[j]]=a[i]+1;
                
                int t=i/p[i];
                if(t==1)K[i*prime[j]]=1;
                else    K[i*prime[j]]=(a[t]==a[i*prime[j]]?-K[t]:0);
                break;
            }
            p[i*prime[j]]=prime[j];
            a[i*prime[j]]=1;
            K[i*prime[j]]=(a[i]==a[i*prime[j]])?(-K[i]):0;
        }
    }
    for(int i=1;i<=10000000;i++)K[i]+=K[i-1];
}


int main()
{
    get_K();
    int T_T;
    scanf("%d",&T_T);
    while(T_T--)
    {
        int n,m;
        scanf("%d%d",&n,&m);
        LL ans=0,last;
        for(int T=1;T<=min(n,m);T=last+1)
        {
            last=min(n/(n/T),m/(m/T));
            ans+=(LL(n/T))*(LL(m/T))*(LL(K[last]-K[T-1]));
        }
        printf("%lld\n",ans);
    }
    return 0;
}

 

posted @ 2018-03-22 09:17  AKCqhzdy  阅读(190)  评论(0编辑  收藏  举报