题目大意:求$sum_{i=1}^{n}sum_{j=1}^{m}lcm(i,j)$的和
易得$sum_{i=1}^{n}sum_{j=1}^{m}frac{ij}{gcd(i,j)}$
套路1:提取出$gcd$
$sum_{k=1}^{n}frac{1}{k}sum_{i=1}^{n}sum_{j=1}^{m}ij[gcd(i,j)==k]$
$sum_{k=1}^{n}ksum_{i=1}^{left lfloor frac{n}{k} ight floor}sum_{j=1}^{left lfloor frac{m}{k} ight floor}ij[gcd(i,j)==1]$
$sum_{k=1}^{n}ksum_{i=1}^{left lfloor frac{n}{k} ight floor}sum_{j=1}^{left lfloor frac{m}{k} ight floor}ijsum_{d|gcd(i,j)}mu(d)$
套路2:继续提取$gcd$
$sum_{k=1}^{n}ksum_{d=1}^{left lfloor frac{n}{k} ight floor}mu(d)sum_{i=1}^{left lfloor frac{n}{k} ight floor}sum_{j=1}^{left lfloor frac{m}{k} ight floor}[gcd(i,j)==d]ij$
$sum_{k=1}^{n}ksum_{d=1}^{left lfloor frac{n}{k} ight floor}d^{2}mu(d)sum_{i=1}^{left lfloor frac{n}{kd} ight floor}sum_{j=1}^{left lfloor frac{m}{kd} ight floor}ij$
$sum_{i=1}^{left lfloor frac{n}{kd} ight floor}sum_{j=1}^{left lfloor frac{m}{kd} ight floor}ij$可以$O(1)$计算出来
套路3:令$Q=kd$
$sum_{Q=1}^{n}sum_{i=1}^{left lfloor frac{n}{Q} ight floor}sum_{j=1}^{left lfloor frac{m}{Q} ight floor}ijsum_{d|Q}frac{Q}{d}(d)^{2}mu(d)$
$sum_{d|Q}frac{Q}{d}(d)^{2}mu(d)$显然是积性函数
然后问题就解决了
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #define N 10010000 5 #define maxn 10000000 6 #define ll long long 7 #define uint unsigned int 8 #define rint register int 9 using namespace std; 10 11 int n,m,T,cnt; 12 int mu[N],pr[N],use[N]; 13 int f[N],F[N]; 14 const int mod=100000009; 15 16 void Pre() 17 { 18 mu[1]=1;f[1]=1; 19 for(int i=2;i<=maxn;i++) 20 { 21 if(!use[i]) pr[++cnt]=i,mu[i]=-1,f[i]=(1ll*i*(1-i))%mod; 22 for(rint j=1;j<=cnt&&i*pr[j]<=maxn;j++){ 23 use[i*pr[j]]=1; 24 if(i%pr[j]){ 25 mu[i*pr[j]]=-mu[i]; 26 f[i*pr[j]]=1ll*f[i]*f[pr[j]]%mod; 27 }else{ 28 mu[i*pr[j]]=0; 29 f[i*pr[j]]=1ll*f[i]*pr[j]%mod; 30 break; 31 } 32 } 33 } 34 for(int i=1;i-4<=maxn;i+=4) 35 { 36 F[i+0]=(1ll*F[i-1]+f[i+0])%mod; 37 F[i+1]=(1ll*F[i+0]+f[i+1])%mod; 38 F[i+2]=(1ll*F[i+1]+f[i+2])%mod; 39 F[i+3]=(1ll*F[i+2]+f[i+3])%mod; 40 } 41 } 42 ll solve(int n,int m) 43 { 44 ll ans=0,sn,sm; 45 if(n>m) swap(n,m); 46 for(int i=1,la;i<=n;i=la+1) 47 { 48 la=min(n/(n/i),m/(m/i)); 49 sn=(1ll*(n/i)*(n/i+1)/2)%mod; 50 sm=(1ll*(m/i)*(m/i+1)/2)%mod; 51 (ans+=1ll*sn*sm%mod*(F[la]-F[i-1]))%=mod; 52 }ans=(ans%mod+mod)%mod; 53 return ans; 54 } 55 56 int main() 57 { 58 //freopen("t1.in","r",stdin); 59 scanf("%d",&T); 60 Pre(); 61 int n,m; 62 while(T--) 63 { 64 scanf("%d%d",&n,&m); 65 printf("%lld ",solve(n,m)); 66 } 67 return 0; 68 }
调试部分的代码..留个纪念吧
1 int ps[N],son[N],d[N],num,nson; 2 void dfs_son(int s,int dep) 3 { 4 if(dep>num) {son[++nson]=s;return;} 5 for(int j=0;j<=d[dep];j++) 6 dfs_son(s,dep+1),s*=ps[dep]; 7 } 8 ll g[N]; 9 void check() 10 { 11 for(int i=1;i<=maxn;i++){ 12 int sq=sqrt(i),x=i; 13 num=nson=0; 14 for(int j=1;j<=cnt&&pr[j]<=sq;j++) 15 if(x%pr[j]==0){ 16 ps[++num]=pr[j]; 17 while(x%pr[j]==0) d[num]++,x/=pr[j]; 18 } 19 if(x!=1) ps[++num]=x,d[num]=1; 20 dfs_son(1,1); 21 for(int j=1;j<=nson;j++) 22 (g[i]+=mu[son[j]]*son[j]%mod)%=mod, 23 son[j]=0; 24 g[i]=g[i]*i%mod; 25 for(int i=1;i<=num;i++) 26 d[i]=0; 27 } 28 }