BZOJ 1101 [POI2007]Zap ——Dirichlet积

【题目分析】

    Dirichlet积+莫比乌斯函数。

    对于莫比乌斯函数直接筛出处理前缀和。

    对于后面向下取整的部分,可以分成sqrt(n)+sqrt(m)部分分别计算

    学习了一下线性筛法。

    积性函数可以在O(n)的时间内算出。

【代码】

#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>

#include <map>
#include <set>
#include <queue>
#include <string>
#include <iostream>
#include <algorithm>

using namespace std;

#define maxn 50005
#define inf 0x3f3f3f3f
#define F(i,j,k) for (int i=j;i<=k;++i)
#define D(i,j,k) for (int i=j;i>=k;--i)

void Finout()
{
    #ifndef ONLINE_JUDGE
    freopen("in.txt","r",stdin);
//    freopen("wa.txt","w",stdout);
//    freopen("ac.txt","w",stdout);
    #endif
}

int Getint()
{
    int x=0,f=1; char ch=getchar();
    while (ch<'0'||ch>'9') {if (ch=='-') f=-1; ch=getchar();}
    while (ch>='0'&&ch<='9') {x=x*10+ch-'0'; ch=getchar();}
    return x*f;
}

int pmu[maxn],mu[maxn],vis[maxn],pri[maxn],top=0;

void init()
{
	mu[1]=1;vis[1]=1;
	F(i,2,maxn-1)
	{
		if (!vis[i]) {vis[i]=1;pri[++top]=i;mu[i]=-1;}
		for (int j=1;j<=top&&i*pri[j]<maxn;++j)
		{
			vis[i*pri[j]]=1;
			if (i%pri[j]==0) {break;}
			else mu[pri[j]*i]=-mu[i];
		}
	}
	F(i,1,maxn-1) pmu[i]=pmu[i-1]+mu[i];
}

int t;

int main()
{
	init();
    Finout();
    t=Getint();
    while (t--)
    {
    	int ans=0;
    	int a=Getint(),b=Getint(),d=Getint();
    	a/=d; b/=d;
    	int la,lb,nowa,nowb,l,r=a;
    	while (r)
    	{
//    		cout<<"r is "<<r<<endl;
    		nowa=a/r;nowb=b/r;
    		la=a/(nowa+1)+1;lb=b/(nowb+1)+1;
//    		cout<<"la is "<<la<<" lb is "<<lb<<endl;
    		l=max(la,lb);
    		ans+=nowa*nowb*(pmu[r]-pmu[l-1]);
    		r=l-1;
		}
		printf("%d\n",ans);
	}
}

  

posted @ 2017-01-15 18:08  SfailSth  阅读(105)  评论(0编辑  收藏  举报