bzoj2693: jzptab
最终的柿子:sigema(min)T K(T)*S(T)
K(T)=sigema(n/T)i sigema(m/T)j i*j
S(T)=sigema(d|T)u(d)*d^d*T
收获:写柿子的时候不能省掉范围。。。要分块找向下整除
#include<cstdio> #include<iostream> #include<cstring> #include<cstdlib> #include<algorithm> #include<cmath> using namespace std; typedef long long LL; const LL mod=100000009; LL MOD(LL x){return (x%mod+mod)%mod;} LL sqr(LL x){return x*x%mod;} LL n,m; int pr;LL prime[10000010]; bool v[10000010]; LL S[10000010]; LL getK(LL x){return ((n/x+1)*(n/x)/2%mod)*((m/x+1)*(m/x)/2%mod)%mod;} void get_prime(int li) { pr=0; S[1]=1; for(LL i=2;i<=li;i++) { if(v[i]==false) { prime[++pr]=i; S[i]=1-i; } for(int j=1;j<=pr&&i*prime[j]<=li;j++) { v[i*prime[j]]=true; if(i%prime[j]==0) { S[i*prime[j]]=S[i]; break; } S[i*prime[j]]=MOD(S[i]-S[i]*prime[j]%mod); } S[i]=(S[i]*i%mod+S[i-1])%mod; } } int main() { // freopen("a.in","r",stdin); // freopen("a.out","w",stdout); get_prime(10000000); int T; scanf("%d",&T); while(T--) { scanf("%lld%lld",&n,&m);LL li=min(n,m); LL ans=0,last; for(LL i=1;i<=li;i=last+1) { last=min(n/(n/i),m/(m/i)); ans=(ans+MOD(S[last]-S[i-1])*getK(i)%mod)%mod; } printf("%lld\n",(ans+mod)%mod); } return 0; }
pain and happy in the cruel world.