bzoj2693--莫比乌斯反演+积性函数线性筛
推导:
设d=gcd(i,j)
利用莫比乌斯函数的性质
令sum(x,y)=(x*(x+1)/2)*(y*(y+1)/2)
令T=d*t
设f(T)=
T可以分块。又由于μ是积性函数,积性函数的约束和仍是积性函数,所以f也是积性函数,可以O(n)线性筛求得。总时间复杂度为
具体筛法看代码。
代码:
#include<iostream> #include<cstdio> #include<cstring> using namespace std; #define mod 100000009 #define _min(a,b) a>b?b:a #define ll long long inline char nc(){ static char buf[100000],*p1=buf,*p2=buf; if(p1==p2){ p2=(p1=buf)+fread(buf,1,100000,stdin); if(p1==p2)return EOF; } return *p1++; } inline void read(int& x){ char c=nc(); for(;c<'0'||c>'9';c=nc()); for(x=0;c>='0'&&c<='9';x=x*10+c-48,c=nc()); } int len; char s[30]; inline void print(ll x){ if(!x){ putchar('0');putchar('\n'); return; } for(len=0;x;x/=10)s[++len]=x%10; for(;len;len--)putchar(s[len]+48); putchar('\n'); } inline int sum(ll x,ll y){ return (x*(x+1)/2%mod)*(y*(y+1)/2%mod)%mod; } int T,i,j,k,n,m,ma,num,p[1000001],x,a[10001],b[10001],ans; ll f[10000001]; bool v[10000001]; int main() { read(T); for(i=1;i<=T;i++){ read(a[i]);read(b[i]); if(a[i]>b[i]){k=a[i];a[i]=b[i];b[i]=k;} if(a[i]>ma)ma=a[i]; } f[1]=1; for(i=2;i<=ma;i++){ if(!v[i]){ p[++num]=i; f[i]=-(1LL*i*(i-1)%mod); } for(j=1;j<=num&&p[j]*i<=ma;j++){ v[p[j]*i]=1; if(i%p[j])f[i*p[j]]=f[i]*f[p[j]]%mod;else{ f[i*p[j]]=f[i]*p[j]%mod; break; } } } for(i=2;i<=ma;i++)f[i]=(f[i]+f[i-1])%mod; for(k=1;k<=T;k++){ ans=0; for(i=1;i<=a[k];i=j+1){ j=_min(a[k]/(a[k]/i),b[k]/(b[k]/i)); ans=(ans+(f[j]-f[i-1])*sum(a[k]/i,b[k]/i)%mod)%mod; } print((ans+mod)%mod); } return 0; }