学习课件: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(a−1,d,k)−g(b,c−1,k)+g(a−1,c−1,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)==x∗i的对数,
x
∈
Z
x \in Z
x∈Z,
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]=∑x∣dnf[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]=∑x∣dnu(d/x)∗g[d]=∑x∣dnu(d/x)∗⌊n/x⌋∗⌊m/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/d⌋⌊m/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=p1a1∗p2a2∗...∗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)=(p1−1p1a1+1−1)∗(p2−1p2a2+1−1)∗...∗(pn−1pnan+1−1)
求数的约数和除了用上面提到的方法,这题也可以用朴素的暴力方法,有线性的方法,但弱鸡看不懂。。
#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
<
=
1
e
7
\sum_{i=1}^n\sum_{j=1}^mlcm(i,j),n,m<=1e7
∑i=1n∑j=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=1n∑j=1mlcm(i,j)=∑i=1n∑j=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)=∑i−1x∑j=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)=i−1∑xj=1∑yij[(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=1∑xj=1∑yijd∣(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=1∑xu(d)d∣i∑xid∣j∑yj
=
∑
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=1∑xu(d)d2i=1∑⌊dx⌋ij=1∑⌊dy⌋j
=
∑
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=1∑xu(d)d22⌊dx⌋(⌊dx⌋+1)2⌊dy⌋(⌊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=1∑nF(⌊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=1∑ndi=1∑⌊dn⌋u(i)i22⌊i⌊dn⌋⌋(⌊i⌊dn⌋⌋+1)2⌊i⌊dm⌋⌋(⌊i⌊dm⌋⌋+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=1∑ndi=1∑⌊dn⌋u(i)i22⌊din⌋(⌊din⌋+1)2⌊dim⌋(⌊dim⌋+1)
现在可以
O
(
n
n
)
=
O
(
n
)
O(\sqrt n \sqrt n)=O(n)
O(nn)=O(n)查询了,可以继续化简,令
T
=
d
i
T=di
T=di,则
i
∣
T
,
d
=
T
/
i
i|T,d=T/i
i∣T,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=1∑ndi=1∑⌊dn⌋u(i)i22⌊din⌋(⌊din⌋+1)2⌊dim⌋(⌊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=1∑n2⌊Tn⌋(⌊Tn⌋+1)2⌊Tm⌋(⌊Tm⌋+1)i∣T∑iTu(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=1∑n2⌊Tn⌋(⌊Tn⌋+1)2⌊Tm⌋(⌊Tm⌋+1)Ti∣T∑u(i)i
设
g
(
T
)
=
T
∑
i
∣
T
u
(
i
)
i
g(T)=T\sum_{i|T}u(i)i
g(T)=T∑i∣Tu(i)i,
f
(
T
)
=
∑
i
∣
T
u
(
i
)
i
f(T)=\sum_{i|T}u(i)i
f(T)=∑i∣Tu(i)i,则
g
(
T
)
=
T
∗
f
(
T
)
g(T)=T*f(T)
g(T)=T∗f(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)=∑i∣kpyu(i)i
当
p
y
∣
k
p_y|k
py∣k时,如果i取的因子不包含新加入的
p
y
p_y
py,答案为
f
(
k
)
f(k)
f(k);当i取的因子包含新加入的
p
y
p_y
py时,此时
p
y
p_y
py已经
>
=
2
>=2
>=2,所以
u
(
i
)
=
0
u(i)=0
u(i)=0,贡献为0,综上,当
p
y
∣
k
p_y|k
py∣k答案为
f
(
k
)
f(k)
f(k)
当
p
y
∤
k
p_y\nmid k
py∤k时,当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
i∣T∑u(i)i=apy∣kpy∑u(apy)apy
=
p
y
∑
a
∣
k
u
(
a
)
u
(
p
y
)
a
~~~~~~~~~~~~~~~~=p_y\sum_{a|k}u(a)u(p_y)a
=pya∣k∑u(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)
=−pya∣k∑u(a)a=−pyf(k)
综上,当
p
y
∤
k
p_y\nmid k
py∤k时,答案为
(
1
−
p
y
)
f
(
k
)
(1-p_y)f(k)
(1−py)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=1∑n2⌊Tn⌋(⌊Tn⌋+1)2⌊Tm⌋(⌊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
和上题相同,多次查询,上述代码可以解决。