[BZOJ3309] DZY Loves Math - 莫比乌斯反演

先链popoqqq大爷的题解

    然后看本蒟蒻口胡(雾),毕竟50题了qwq

    嗯首先莫比乌斯反演在popoqqq大爷的题解里面已经很详细了。。

    然后我就贴代码放筛法了……莫比乌斯反演一下,O(n)预处理,O(Tk)分块查询。。k=两个输入的数的约数交集的大小 - -

    然后就A了啊 - - (其实我还不是很懂啊qwq所以太弱也讲不清什么qwq

#include "stdio.h"
#include "math.h"
#include "stdlib.h"
#include "algorithm"
#include "iostream"
#define rep(f,a,b) for(f=a;f<=b;f++)
#define run(f,to) for(f=1;f<=to;f++)
#define re(f) for(f=2;f<=fto;f++)
#define fto 10000000
#define N 10000005
#define M 2000005
using namespace std;

typedef long long ll;
inline int read(){
	int v=0; char ch=getchar();
	while (ch<'0'||ch>'9') ch=getchar();
	while (ch<='9'&&ch>='0') { v=v*10+ch-'0'; ch=getchar();}
	return v;
}
ll g[N],sg[N]; int pri[M],len,ti[N],mnl[N]; bool flag[N];

void build(){ // 筛法:线性筛g函数,pri[x]代表x的只包含其最小质因子的最大的约数,ti代表其次数
<pre name="code" class="cpp">	//然后显然pri<=i,所以筛法就很清晰了啊……<del>只要理解了线性筛的,这个应该不难吧(除了我这种大蒟蒻TAT</del>
int i,j,k; re(i){if(!flag[i]) g[i]=ti[i]=1,mnl[i]=i,pri[++len]=i;for (j=1;pri[j]*i<=fto;j++){k=i*pri[j]; flag[k]=true; if (i%pri[j]==0){ ti[k]=ti[i]+1; mnl[k]=mnl[i]*pri[j]; int tmp=i/mnl[i];g[k]=tmp==1?1: ti[tmp]==ti[k]?-g[tmp]:0; break;}ti[k]=1; mnl[k]=pri[j]; g[k]=ti[i]==1?-g[i]:0;}}re(i) sg[i]=sg[i-1]+g[i];}void work(){int q=read(),a,b,i,j,last,c;run(j,q){a=read(),b=read(); ll ans=0;for (i=1,c=min(a,b);i<=c;i=last+1){last=min(a/(a/i),b/(b/i));ans+=(ll)(a/i)*(b/i)*(sg[last]-sg[i-1]);}printf("%lld\n",ans);}}int main(){build(); work();return 0;}

 
 

你可能感兴趣的:([BZOJ3309] DZY Loves Math - 莫比乌斯反演)