莫比乌斯反演

学习课件:popoqqq课件,可以百度下载

Gcd

Bzoj2818:
题解来源:https://www.cnblogs.com/Emiya-wjk/p/9991997.html
题意:给定整数N(1<=N<=10000000),求1<=x,y<=N,gcd(x,y)为素数的对数
题解:
在这里插入图片描述

#include<iostream>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<cstdio>
#include<iomanip>
#include<cstdlib>
#define MAXN 0x7fffffff
typedef long long LL;
const int N=10000005;
using namespace std;
inline int Getint(){register int x=0,f=1;register char ch=getchar();while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}while(isdigit(ch)){x=x*10+ch-'0';ch=getchar();}return x*f;}
int mu[N],prime[N]; 
bool vis[N];

int main(){
    int n=Getint();
    mu[1]=1;
    for(int i=2;i<n;i++){
        if(!vis[i])prime[++prime[0]]=i,mu[i]=-1;
        for(int j=1;j<=prime[0]&&i*prime[j]<n;j++){
            vis[i*prime[j]]=1;
            if(i%prime[j]==0)break;
            mu[i*prime[j]]=-mu[i];
        }
    }
    LL ans=0;
    for(int i=1;i<=prime[0];i++)
        for(int j=1;j*prime[i]<=n;j++)
            ans+=(LL)mu[j]*(n/j/prime[i])*(n/j/prime[i]);
    cout<<ans;
    return 0;
}

能量采集

noi 2010
题解来源:https://www.cnblogs.com/emiya-wjk/p/9996805.html
在这里插入图片描述

#include<iostream>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<cstdio>
#include<iomanip>
#include<cstdlib>
#define MAXN 0x7fffffff
typedef long long LL;
const int N=100005;
using namespace std;
inline int Getint(){register int x=0,f=1;register char ch=getchar();while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}while(isdigit(ch)){x=x*10+ch-'0';ch=getchar();}return x*f;}
int mu[N],prime[N];
bool vis[N];
int main(){
    int n=Getint(),m=Getint();if(n>m)swap(n,m); 
    mu[1]=1;
    for(int i=2;i<=n;i++){
        if(!vis[i])prime[++prime[0]]=i,mu[i]=-1;
        for(int j=1;j<=prime[0]&&1ll*i*prime[j]<=n;j++){
            vis[i*prime[j]]=1;
            if(i%prime[j]==0)break;
            mu[i*prime[j]]=-mu[i];
        }
    }
    LL ans=0;
    for(int d=1;d<=n;d++){
        LL ret=0;
        for(int x=1;x*d<=n;x++)
            ret+=1ll*mu[x]*(n/x/d)*(m/x/d);
        ans+=ret*d;
    }
    cout<<2*ans-1ll*n*m;
    return 0;
}

Problem b

Bzoj 2301
题解来源:https://blog.csdn.net/outer_form/article/details/50590197
题意:n次询问,每次询问给出a,b,c,d,k,求在a<=x<=b,c<=y<=d,满足gcd(x,y)是k的(x,y)的对数。
令g(n,m,k)表示在1<=x<=n,1<=y<=m,满足gcd(x,y)是k的(x,y)的对数。 那么由容斥原理可得
a n s = g ( c , d , k ) − − g ( a − 1 , d , k ) − g ( b , c − 1 , k ) + g ( a − 1 , c − 1 , k ) ans=g(c,d,k)--g(a-1,d,k)-g(b,c-1,k)+g(a-1,c-1,k) ans=g(c,d,k)g(a1,d,k)g(b,c1,k)+g(a1,c1,k)
其中 g ( n , m , k ) = g ( n / k , m / k , 1 ) g(n,m,k)=g(n/k,m/k,1) g(n,m,k)=g(n/k,m/k,1),我们根据gcd那道,
令f[i]为 g c d ( x , y ) = = i gcd(x,y)==i gcd(x,y)==i的对数, g [ i ] g[i] g[i] g c d ( x , y ) = = x ∗ i gcd(x,y)==x*i gcd(x,y)==xi的对数, x ∈ Z x \in Z xZ g [ i ] = ( n / i ) ∗ ( m / i ) g[i]=(n/i)*(m/i) g[i]=(n/i)(m/i) g [ x ] = ∑ x ∣ d n f [ d ] g[x]=\sum_{x|d}^n f[d] g[x]=xdnf[d],反演后
f [ x ] = ∑ x ∣ d n u ( d / x ) ∗ g [ d ] = ∑ x ∣ d n u ( d / x ) ∗ ⌊ n / x ⌋ ∗ ⌊ m / x ⌋ f[x]=\sum_{x|d}^n u(d/x)*g[d]=\sum_{x|d}^n u(d/x)*\lfloor n/x\rfloor*\lfloor m/x\rfloor f[x]=xdnu(d/x)g[d]=xdnu(d/x)n/xm/x
当x=1时, f [ 1 ] = ∑ d = 1 m i n ( n , m ) u ( d ) ⌊ n / d ⌋ ⌊ m / d ⌋ f[1]=\sum_{d=1}^{min(n,m)} u(d)\lfloor n/d\rfloor \lfloor m/d \rfloor f[1]=d=1min(n,m)u(d)n/dm/d,由于 ⌊ n / x ⌋ \lfloor n/x \rfloor n/x取值最多只有 2 n 2\sqrt n 2n 个,我们算出 u u u的前缀和sum,然后只需要在 O ( 2 ( n + m ) ) O(2(\sqrt n +\sqrt m)) O(2(n +m ))的时间回答每次查询即可。

#include<iostream>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<cstdio>
#include<iomanip>
#include<cstdlib>
#define MAXN 0x7fffffff
typedef long long LL;
const int N=50005;
using namespace std;
inline int Getint(){register int x=0,f=1;register char ch=getchar();while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}while(isdigit(ch)){x=x*10+ch-'0';ch=getchar();}return x*f;}
int mu[N],prime[N],sum[N];
bool vis[N];
int Cal(int n,int m)
{
	if(n>m) swap(n,m);
	int last,res=0;
	for(int i=1;i<=n;i=last+1){
		last=min(n/(n/i),m/(m/i));
		res+=(n/i)*(m/i)*(sum[last]-sum[i-1]);
	}
	return res;
}
int n,a,b,c,d,k;
int main(){
    n=50000;
    sum[1]=mu[1]=1;sum[0]=0;
    for(int i=2;i<=n;i++){
        if(!vis[i])prime[++prime[0]]=i,mu[i]=-1;
        for(int j=1;j<=prime[0]&&1ll*i*prime[j]<=n;j++){
            vis[i*prime[j]]=1;
            if(i%prime[j]==0)break;
            mu[i*prime[j]]=-mu[i];
        }
        sum[i]=mu[i]+sum[i-1];
    }
    n=Getint();
    for(int i=1;i<=n;i++){
    	a=Getint();b=Getint();c=Getint();d=Getint();
    	k=Getint();a--;c--;
    	int ans=Cal(b/k,d/k)+Cal(a/k,c/k)-Cal(b/k,c/k)-Cal(a/k,d/k);
    	cout<<ans<<endl;
	}
    return 0;
}

YY的GCD

Bzoj 2820
题解来源:http://hzwer.com/6142.html
在这里插入图片描述
在这里插入图片描述
可以线筛预处理F,按照素数粗略个数n/logn以及调和级数求和nlogn来看暴力的复杂度接近On,处理完F以后就是喜闻乐见的下底函数分块。
莫得提交,代码正确性待验证。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=50005;

inline int read()
{
	int res=0;
	char ch;
	while((ch=getchar())<'0'||ch>'9');
	while(ch>='0'&&ch<='9') res=(res<<3)+(res<<1)+ch-'0',ch=getchar();
	return res; 
}
int mu[maxn],prime[maxn];
int n,m;
bool vis[maxn];
ll f[maxn];
void getphi()
{
	memset(vis,0,sizeof(vis));
	memset(mu,0,sizeof(mu));
	mu[1]=1;
	for(int i=2;i<maxn;i++){
		if(!vis[i]) prime[++prime[0]]=i,mu[i]=-1;
		for(int j=1;j<=prime[0]&&1LL*i*prime[j]<maxn;j++){
			vis[i*prime[j]]=1;
			if(i%prime[j]==0) break;
			mu[i*prime[j]]=-mu[i];
		}
	}
	memset(f,0,sizeof(f));
	for(int i=1;i<=prime[0];i++){
		int p=prime[i];
		for(int j=1;j*p<maxn;j++) f[j*p]+=mu[j];
	}
	for(int i=1;i<maxn;i++) f[i]+=f[i-1];
}
int main(){
	getphi();
    int t=read();
    while(t--){
    	ll ans=0;
    	n=read();m=read();
    	if(n>m) swap(n,m);
    	for(int i=1,j;i<=n;i=j+1){
    		j=min(n/(n/i),m/(m/i));
    		ans+=(f[j]-f[i-1])*(n/i)*(m/i);
		}
		printf("%lld\n",ans);
	}
    return 0;
}

数表

Bzoj 3529
参考代码:https://www.cnblogs.com/gzez181027/p/bzoj3529.html
题解:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
PS:求一个数x的约数和,令 x = p 1 a 1 ∗ p 2 a 2 ∗ . . . ∗ p n a n x=p_1^{a_1}*p_2^{a_2}*...*p_n^{a_n} x=p1a1p2a2...pnan,那么x的约数和为
s u m = ( p 1 0 + p 1 1 + . . + p 1 a 1 ) ∗ ( p 2 0 + p 2 1 + . . + p 2 a 2 ) ∗ . . . ∗ ( p n 0 + . . + p n a n ) = ( p 1 a 1 + 1 − 1 p 1 − 1 ) ∗ ( p 2 a 2 + 1 − 1 p 2 − 1 ) ∗ . . . ∗ ( p n a n + 1 − 1 p n − 1 ) sum=(p_1^{0}+p_1^{1}+..+p_1^{a_1})*(p_2^{0}+p_2^{1}+..+p_2^{a_2})*...*(p_n^{0}+..+p_n^{a_n}) =(\frac{p_1^{a_1+1}-1}{p_1-1})*(\frac{p_2^{a_2+1}-1}{p_2-1})*...*(\frac{p_n^{a_n+1}-1}{p_n-1}) sum=(p10+p11+..+p1a1)(p20+p21+..+p2a2)...(pn0+..+pnan)=(p11p1a1+11)(p21p2a2+11)...(pn1pnan+11)
求数的约数和除了用上面提到的方法,这题也可以用朴素的暴力方法,有线性的方法,但弱鸡看不懂。。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=100001;
const int maxm=20010;
inline int read()
{
	int res=0;
	char ch;
	while((ch=getchar())<'0'||ch>'9');
	while(ch>='0'&&ch<='9') res=(res<<3)+(res<<1)+ch-'0',ch=getchar();
	return res; 
}
int mu[maxn],prime[maxn];
int n,m,a;
bool vis[maxn];
struct node{
	int id,val;
}f[maxn];
bool cmp(const node &x,const node &y)
{
	return x.val<y.val;
}
struct Query{
	int id,n,m,a;
}q[maxm];
int ans[maxm];
bool cmp2(const Query &x,const Query &y)
{
	return x.a<y.a;
}
void getphi()
{
	memset(vis,0,sizeof(vis));
	memset(mu,0,sizeof(mu));
	mu[1]=1;
	for(int i=2;i<maxn;i++){
		if(!vis[i]) prime[++prime[0]]=i,mu[i]=-1;
		for(int j=1;j<=prime[0]&&1LL*i*prime[j]<maxn;j++){
			vis[i*prime[j]]=1;
			if(i%prime[j]==0) break;
			mu[i*prime[j]]=-mu[i];
		}
	}
	for(int i=1;i<maxn;i++) f[i].id=i,f[i].val=0;
	for(int i=1;i<maxn;i++)
		for(int j=i;j<maxn;j+=i)
			f[j].val+=i; 
	sort(f+1,f+maxn,cmp);
}
int s[maxn];
int lowbit(int x)
{
	return x&(-x);
}
void Add(int x,int val)
{
	for(;x<maxn;x+=lowbit(x))
		s[x]+=val;
	return;
}
int query(int x)
{
	int res=0;
	for(;x;x-=lowbit(x)) res+=s[x];
	return res;
}
int solve(int n,int m)
{
	int res=0;
	if(n>m) swap(n,m);
	for(int i=1,j;i<=n;i=j+1){
		j=min(n/(n/i),m/(m/i));
		res+=(query(j)-query(i-1))*(n/i)*(m/i);
	}
	return res&0x7fffffff;//这里模为(1LL<<31)等价下面 减法取模
//	return (res+(1LL<<31))%(1LL<<31);
}
int main()
{
	getphi();
	scanf("%d",&m);
	for(int i=1;i<=m;i++){
		scanf("%d%d%d",&q[i].n,&q[i].m,&q[i].a);
		q[i].id=i;
	}
	sort(q+1,q+m+1,cmp2);
	for(int i=1,j=1;i<=m;i++){
		for(;j<maxn&&f[j].val<=q[i].a;j++)
			for(int k=f[j].id;k<maxn;k+=f[j].id)
				Add(k,f[j].val*mu[k/f[j].id]);
		ans[q[i].id]=solve(q[i].n,q[i].m);
	}
	for(int i=1;i<=m;i++) printf("%d\n",ans[i]);
	return 0;
}

Crash的数字表格

Bzoj 2154
题意:求 ∑ i = 1 n ∑ j = 1 m l c m ( i , j ) , n , m &lt; = 1 e 7 \sum_{i=1}^n\sum_{j=1}^mlcm(i,j),n,m&lt;=1e7 i=1nj=1mlcm(i,j),n,m<=1e7
题解&代码:https://www.cnblogs.com/iwtwiioi/p/4268926.html
题解:
下面设n<m
∑ i = 1 n ∑ j = 1 m l c m ( i , j ) = ∑ i = 1 n ∑ j = 1 m i j ( i , j ) \sum_{i=1}^n \sum_{j=1}^m lcm(i,j)=\sum_{i=1}^n \sum_{j=1}^m \frac{ij}{(i,j)} i=1nj=1mlcm(i,j)=i=1nj=1m(i,j)ij
然后枚举 d = ( i , j ) d=(i,j) d=(i,j),那么确定i,j怎么取,显然我们只只需要先除去i和j的d,也就是 ( i / d , j / d ) = 1 (i/d,j/d)=1 (i/d,j/d)=1就行了,那么设 F ( x , y ) = ∑ i − 1 x ∑ j = 1 y i j [ ( i , j ) = = 1 ] F(x,y)=\sum_{i-1}^ x \sum_{j=1}^y ij[(i,j)==1] F(x,y)=i1xj=1yij[(i,j)==1],那么原式变成 ∑ d = 1 n d 2 F ( ⌊ n d ⌋ , ⌊ m d ⌋ ) d \sum_{d=1}^n \frac {d^2F(\lfloor \frac{n}{d}\rfloor,\lfloor \frac{m}{d} \rfloor)}{d} d=1ndd2F(dn,dm)
考虑 F ( x , y ) F(x,y) F(x,y)
F ( x , y ) = ∑ i − 1 x ∑ j = 1 y i j [ ( i , j ) = = 1 ] F(x,y)=\sum_{i-1}^ x \sum_{j=1}^yij[(i,j)==1] F(x,y)=i1xj=1yij[(i,j)==1]
           = ∑ i = 1 x ∑ j = 1 y i j ∑ d ∣ ( i , j ) u ( d ) ~~~~~~~~~~=\sum_{i=1}^ x \sum_{j=1}^y ij\sum_{d|(i,j)} u(d)           =i=1xj=1yijd(i,j)u(d)
           = ∑ d = 1 x u ( d ) ∑ d ∣ i x i ∑ d ∣ j y j ~~~~~~~~~~=\sum_{d=1}^{x} u(d) \sum_{d|i}^x i \sum_{d|j}^y j           =d=1xu(d)dixidjyj
           = ∑ d = 1 x u ( d ) d 2 ∑ i = 1 ⌊ x d ⌋ i ∑ j = 1 ⌊ y d ⌋ j ~~~~~~~~~~=\sum_{d=1}^x u(d)d^2\sum_{i=1}^{\lfloor \frac{x}{d} \rfloor}i\sum_{j=1}^{\lfloor \frac{y}{d}\rfloor}j           =d=1xu(d)d2i=1dxij=1dyj
                                         = ∑ d = 1 x u ( d ) d 2 ⌊ x d ⌋ ( ⌊ x d ⌋ + 1 ) 2 ⌊ y d ⌋ ( ⌊ y d ⌋ + 1 ) 2 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~=\sum_{d=1}^xu(d)d^2 \frac{\lfloor \frac{x}{d} \rfloor (\lfloor \frac{x}{d}\rfloor+1)}{2}\frac{\lfloor \frac{y}{d} \rfloor (\lfloor \frac{y}{d}\rfloor+1)}{2}                                         =d=1xu(d)d22dx(dx+1)2dy(dy+1)
带回原式得:
∑ d = 1 n F ( ⌊ n d ⌋ , ⌊ m d ⌋ ) \sum_{d=1}^n F(\lfloor \frac{n}{d}\rfloor,\lfloor \frac{m}{d} \rfloor) d=1nF(dn,dm)
                                                  = ∑ d = 1 n d ∑ i = 1 ⌊ n d ⌋ u ( i ) i 2 ⌊ ⌊ n d ⌋ i ⌋ ( ⌊ ⌊ n d ⌋ i ⌋ + 1 ) 2 ⌊ ⌊ m d ⌋ i ⌋ ( ⌊ ⌊ m d ⌋ i ⌋ + 1 ) 2 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~=\sum_{d=1}^nd\sum_{i=1}^{\lfloor \frac{n}{d}\rfloor}u(i)i^2 \frac{\lfloor \frac{\lfloor \frac{n}{d} \rfloor}{i}\rfloor({\lfloor \frac{\lfloor \frac{n}{d} \rfloor}{i}\rfloor}+1)}{2}\frac{{\lfloor \frac{\lfloor \frac{m}{d} \rfloor}{i}\rfloor}({\lfloor \frac{\lfloor \frac{m}{d} \rfloor}{i}\rfloor}+1)}{2}                                                  =d=1ndi=1dnu(i)i22idn(idn+1)2idm(idm+1)
                                      = ∑ d = 1 n d ∑ i = 1 ⌊ n d ⌋ u ( i ) i 2 ⌊ n d i ⌋ ( ⌊ n d i ⌋ + 1 ) 2 ⌊ m d i ⌋ ( ⌊ m d i ⌋ + 1 ) 2 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~=\sum_{d=1}^nd\sum_{i=1}^{\lfloor \frac{n}{d}\rfloor}u(i)i^2\frac{\lfloor \frac{n}{di} \rfloor(\lfloor \frac{n}{di} \rfloor+1)}{2}\frac{\lfloor \frac{m}{di} \rfloor(\lfloor \frac{m}{di} \rfloor+1)}{2}                                      =d=1ndi=1dnu(i)i22din(din+1)2dim(dim+1)
现在可以 O ( n n ) = O ( n ) O(\sqrt n \sqrt n)=O(n) O(n n )=O(n)查询了,可以继续化简,令 T = d i T=di T=di,则 i ∣ T , d = T / i i|T,d=T/i iT,d=T/i,换掉指标,得
= ∑ d = 1 n d ∑ i = 1 ⌊ n d ⌋ u ( i ) i 2 ⌊ n d i ⌋ ( ⌊ n d i ⌋ + 1 ) 2 ⌊ m d i ⌋ ( ⌊ m d i ⌋ + 1 ) 2 =\sum_{d=1}^nd\sum_{i=1}^{\lfloor \frac{n}{d}\rfloor}u(i)i^2\frac{\lfloor \frac{n}{di} \rfloor(\lfloor \frac{n}{di} \rfloor+1)}{2}\frac{\lfloor \frac{m}{di} \rfloor(\lfloor \frac{m}{di} \rfloor+1)}{2} =d=1ndi=1dnu(i)i22din(din+1)2dim(dim+1)
= ∑ T = 1 n ⌊ n T ⌋ ( ⌊ n T ⌋ + 1 ) 2 ⌊ m T ⌋ ( ⌊ m T ⌋ + 1 ) 2 ∑ i ∣ T T i u ( i ) i 2 =\sum_{T=1}^n\frac{\lfloor \frac{n}{T} \rfloor(\lfloor \frac{n}{T} \rfloor+1)}{2}\frac{\lfloor \frac{m}{T} \rfloor(\lfloor \frac{m}{T} \rfloor+1)}{2}\sum_{i|T}\frac{T}{i}u(i)i^2 =T=1n2Tn(Tn+1)2Tm(Tm+1)iTiTu(i)i2
= ∑ T = 1 n ⌊ n T ⌋ ( ⌊ n T ⌋ + 1 ) 2 ⌊ m T ⌋ ( ⌊ m T ⌋ + 1 ) 2 T ∑ i ∣ T u ( i ) i =\sum_{T=1}^n\frac{\lfloor \frac{n}{T} \rfloor(\lfloor \frac{n}{T} \rfloor+1)}{2}\frac{\lfloor \frac{m}{T} \rfloor(\lfloor \frac{m}{T} \rfloor+1)}{2}T\sum_{i|T}u(i)i =T=1n2Tn(Tn+1)2Tm(Tm+1)TiTu(i)i
g ( T ) = T ∑ i ∣ T u ( i ) i g(T)=T\sum_{i|T}u(i)i g(T)=TiTu(i)i f ( T ) = ∑ i ∣ T u ( i ) i f(T)=\sum_{i|T}u(i)i f(T)=iTu(i)i,则 g ( T ) = T ∗ f ( T ) g(T)=T*f(T) g(T)=Tf(T),考虑求 f ( T ) f(T) f(T),在线性筛中,外层为k,内层为 p y p_y py,求 f ( k p y ) = ∑ i ∣ k p y u ( i ) i f(kp_y)=\sum_{i|kp_y}u(i)i f(kpy)=ikpyu(i)i
p y ∣ k p_y|k pyk时,如果i取的因子不包含新加入的 p y p_y py,答案为 f ( k ) f(k) f(k);当i取的因子包含新加入的 p y p_y py时,此时 p y p_y py已经 &gt; = 2 &gt;=2 >=2,所以 u ( i ) = 0 u(i)=0 u(i)=0,贡献为0,综上,当 p y ∣ k p_y|k pyk答案为 f ( k ) f(k) f(k)
p y ∤ k p_y\nmid k pyk时,当i取的因子不包含新加入的 p y p_y py,答案为 f ( k ) f(k) f(k);当i取的因子包含新加入的 p y p_y py时,指数为1,考虑 i = a p y i=ap_y i=apy
∑ i ∣ T u ( i ) i = ∑ a p y ∣ k p y u ( a p y ) a p y \sum_{i|T}u(i)i=\sum_{ap_y|kp_y}u(ap_y)ap_y iTu(i)i=apykpyu(apy)apy
                 = p y ∑ a ∣ k u ( a ) u ( p y ) a ~~~~~~~~~~~~~~~~=p_y\sum_{a|k}u(a)u(p_y)a                 =pyaku(a)u(py)a
                                 = − p y ∑ a ∣ k u ( a ) a = − p y f ( k ) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~=-p_y\sum_{a|k}u(a)a=-p_yf(k)                                 =pyaku(a)a=pyf(k)
综上,当 p y ∤ k p_y\nmid k pyk时,答案为 ( 1 − p y ) f ( k ) (1-p_y)f(k) (1py)f(k)
预处理求出 f ( T ) f(T) f(T),进而求出 g [ T ) g[T) g[T),最后答案为
∑ T = 1 n ⌊ n T ⌋ ( ⌊ n T ⌋ + 1 ) 2 ⌊ m T ⌋ ( ⌊ m T ⌋ + 1 ) 2 g ( T ) \sum_{T=1}^n\frac{\lfloor \frac{n}{T} \rfloor(\lfloor \frac{n}{T} \rfloor+1)}{2}\frac{\lfloor \frac{m}{T} \rfloor(\lfloor \frac{m}{T} \rfloor+1)}{2}g(T) T=1n2Tn(Tn+1)2Tm(Tm+1)g(T)
再预处理 g ( T ) g(T) g(T)的前缀和,分块查询即可

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod=20101009;
const int maxn=1e7+10;
 
inline int read()
{
    int res=0;
    char ch;
    while((ch=getchar())<'0'||ch>'9');
    while(ch>='0'&&ch<='9') res=(res<<3)+(res<<1)+ch-'0',ch=getchar();
    return res; 
}
int prime[maxn];
int n,m;
bool vis[maxn];
ll g[maxn];
void getphi()
{
//  memset(vis,0,sizeof(vis));
    g[1]=1;
    for(int i=2;i<maxn;++i){
        if(!vis[i]) prime[++prime[0]]=i,g[i]=1-i;
        for(int j=1;j<=prime[0];j++){//&&1LL*i*prime[j]<maxn 
            int tmp=i*prime[j];if(tmp>=maxn) break;
            vis[tmp]=1;
            if(i%prime[j]==0){
                g[tmp]=g[i];
                break;
            }
            g[tmp]=g[i]*(1-prime[j]);//%mod
        }
    }
//  for(int i=2;i<maxn;++i) g[i]=g[i]*i%mod;
    for(int i=2;i<maxn;++i) g[i]=g[i]*i;
    for(int i=1;i<maxn;++i) g[i]+=g[i-1],g[i]%=mod;
}
 
int main(){
    getphi();
    int t=1;
    while(t--){
        scanf("%d%d",&n,&m);if(n>m) swap(n,m);
        ll ans=0,t1,t2;
        for(int i=1,j;i<=n;i=j+1){
            j=min(n/(n/i),m/(m/i));
            t1=(1LL*(n/i)*(n/i+1)/2)%mod;
            t2=(1LL*(m/i)*(m/i+1)/2)%mod;
            
            ans+=(g[j]-g[i-1]+mod)%mod*(t1*t2%mod)%mod;
            ans%=mod;
        }
        printf("%lld\n",((ans%mod)+mod)%mod);
    }
    return 0;
}

jzptab

Bzoj 2693
和上题相同,多次查询,上述代码可以解决。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值