【数论分块】[BZOJ2956、LuoguP2260] 模积和

十年OI一场空,忘记取模见祖宗

题目:

求$$\sum_{i=1}^{n}\sum_{j=1}^{m} (n \bmod i)(m \bmod i)$$

(其中i,j不相等)

 暴力拆式子:

 

 $$ANS=\sum_{i=1}^{n}\sum_{j=1}^{m} (n- \left \lfloor \frac{n}{i} \right \rfloor*i)(m- \left \lfloor \frac{m}{i} \right \rfloor*i)-\sum_{i=1}^{min(n,m)} (n- \left \lfloor \frac{n}{i} \right \rfloor *i)(m- \left \lfloor \frac{m}{i} \right \rfloor *i)$$

$f(n)=\sum_{i=1}^{n} (n- \left \lfloor \frac{n}{i} \right \rfloor *i)$

$g(n)=\sum_{i=1}^{n}(n- \left \lfloor \frac{n}{i} \right \rfloor *i)(m- \left \lfloor \frac{m}{i} \right \rfloor *i)$

不妨设n<=m

则有

$$ANS=f(n)*f(m)-g(n)$$

其中$$g(n)=\sum_{i=1}^{n} n*m-n*\sum_{i=1}^{n} \left \lfloor \frac{m}{i} \right \rfloor *i-m*\sum_{i=1}^{n} \left \lfloor \frac{n}{i} \right \rfloor *i+\sum_{i=1}^{n} \left \lfloor \frac{n}{i} \right \rfloor* \left \lfloor \frac{m}{i} \right \rfloor *i^2$$

且易有$$\sum_{i=1}^{n} i^2=\frac{n*(n+1)*(2*n+1)}{6}$$

预处理6在模19940417意义下的逆元(我用了exgcd)

然后用数论分块把上面一堆东西算一下即可

 

 1 #include<bits/stdc++.h>
 2 #define int long long
 3 #define writeln(x)  write(x),puts("")
 4 #define writep(x)   write(x),putchar(' ')
 5 using namespace std;
 6 inline int read(){
 7     int ans=0,f=1;char chr=getchar();
 8     while(!isdigit(chr)){if(chr=='-') f=-1;chr=getchar();}
 9     while(isdigit(chr)){ans=(ans<<3)+(ans<<1)+chr-48;chr=getchar();}
10     return ans*f;
11 }void write(int x){
12     if(x<0) putchar('-'),x=-x;
13     if(x>9) write(x/10);
14     putchar(x%10+'0');
15 }const int mod = 19940417;
16 int n,m,k;
17 inline void Add(int &x,int y){x+=y;x%=mod;}
18 void exgcd(int a,int b,int &x,int &y){
19     if(b==0)return x=1,y=0,void();
20     exgcd(b,a%b,x,y);
21     int t=x;x=y,y=t-a/b*y;
22 }int inv(int x){
23     int xx,y;
24     exgcd(6,mod,xx,y);
25     xx=(xx%mod+mod)%mod;
26     return xx;
27 }const int inv6=inv(6);
28 int sum(int x){return (x)*(x+1)%mod*(2*x%mod+1)%mod*inv6%mod;}
29 int query1(int l,int r){return ((sum(r)-sum(l-1))%mod+mod)%mod;}
30 int query2(int l,int r){int ans=(r-l+1)*(l+r)/2;return ans%mod;}
31 int calc1(int n){
32     int ans=0;
33     for(int i=1,j,t;i<=n;i=j+1){
34         j=n/(n/i);
35         t=n/i*(i+j)*(j-i+1)/2;
36         t%=mod;
37         Add(ans,t);
38     }ans=n*n%mod-ans;
39     ans=(ans%mod+mod)%mod;
40     return ans;
41 }int calc2(int k){
42     int ans=0;
43     for(int i=1,j,t;i<=n;i=j+1){
44         j=min(n/(n/i),m/(m/i));
45         int s1=n*(m/i)%mod*query2(i,j)%mod;
46         int s2=m*(n/i)%mod*query2(i,j)%mod;
47         int s3=(n/i)*(m/i)%mod*query1(i,j)%mod;
48         Add(s1,s2);
49         Add(ans,s1);
50         ans-=s3;
51         ans=((ans)%mod+mod)%mod;
52     }return ans;
53 }
54 signed main(){
55     n=read(),m=read();
56     if(n>m)swap(n,m);
57     int ans=calc1(n)*calc1(m)%mod;
58     ans-=n*m%mod*n%mod;
59     ans=(ans%mod+mod)%mod;
60     ans+=calc2(n);
61     ans=(ans%mod+mod)%mod;
62     cout<<ans<<endl;
63     return 0;
64 }

 

 

 

 

posted @ 2019-10-21 10:50  zheng_liwen  阅读(153)  评论(0编辑  收藏  举报
/*去广告*/