Description
求
∑i=1n∑j=1mlcm(i,j)(mod100000009)
∑
i
=
1
n
∑
j
=
1
m
l
c
m
(
i
,
j
)
(
mod
100000009
)
多组询问
Solution
同bzoj2154,原本写的就是分块的所以改改就过了
双倍经验
Code
#include <stdio.h>
#include <string.h>
#include <algorithm>
#define rep(i,st,ed) for (int i=st;i<=ed;++i)
typedef long long LL;
const LL MOD=100000009;
const LL ny2=50000004;
const int N=10000005;
int prime[N/10],low[N+1];
short mu[N+1];
bool not_prime[N+1];
LL f[N+1];
void pre_work(int n) {
mu[1]=f[1]=low[1]=1;
rep(i,2,n) {
if (!not_prime[i]) {
prime[++prime[0]]=i;
low[i]=i;
mu[i]=-1;
f[i]=1-i;
}
for (int j=1;i*prime[j]<=n&&j<=prime[0];j++) {
LL x=i*prime[j];
not_prime[x]=1;
if (i%prime[j]==0) {
low[x]=low[i]*prime[j];
mu[x]=0;
if (i==low[i]) {
f[x]=f[i];
} else {
f[x]=(f[i/low[i]]*f[low[i]*prime[j]])%MOD;
}
break;
}
low[x]=prime[j];
f[x]=(f[i]*f[prime[j]])%MOD;
mu[x]=-mu[i];
}
}
rep(i,1,n) f[i]=f[i]*i%MOD;
rep(i,1,n) f[i]=(f[i]+f[i-1])%MOD;
}
LL S(LL n) {
LL ret=n*(n+1)%MOD*ny2%MOD;
return ret;
}
void solve(LL n,LL m) {
LL ans=0;
for (LL i=1,j;i<=n;i=j+1) {
j=std:: min(n/(n/i),m/(m/i));
LL sum=(f[j]-f[i-1]+MOD)%MOD;
LL a=S(n/i); LL b=S(m/i);
LL tot=a*b%MOD*sum%MOD;
ans=(ans+tot)%MOD;
}
if (ans<0) ans=(ans+MOD)%MOD;
printf("%lld\n", ans);
}
void exgcd(LL a,LL b,LL &x,LL &y) {
if (!b) {
x=1; y=0;
return ;
}
exgcd(b,a%b,x,y);
LL tmp=x; x=y; y=tmp-(a/b)*x;
}
int main(void) {
pre_work(N);
int T; scanf("%d",&T);
while (T--) {
LL n,m; scanf("%lld%lld",&n,&m);
if (m<n) std:: swap(n,m);
solve(n,m);
}
return 0;
}

本文介绍了一种解决特定数学问题的方法:求解∑i=1n∑j=1mlcm(i,j) (mod 100000009) 的高效算法。通过预先计算和分块技术来快速响应多组询问。
533

被折叠的 条评论
为什么被折叠?



