题解[清华集训2012]模积和

做这题之前我先做了一道水题也就是这题的弱化版热了热身。

弱化版水题:P2261 [CQOI2007]余数求和

先讲弱化版的。我们知道一个结论就是k%i=k-k/i*i;

那么我们就把取模拆成这种形式。(下文默认i∈[1,n])

很明显∑(k%i)可以拆成∑k-∑k/i*i,化简一下就是n*k-∑k/i*i。然后我们注意到对于一些i,k/i是一样的,就是数论分块里面块的大小。

再结合高斯速算公式来一波,代码就很好写了。

注意特殊情况就是k/l==0,此时不能直接(k/(k/l)),要把r设为n

大概这样。

 

 1 #include<cstdio>
 2 #define it register int
 3 #define il inline
 4 int n,k;
 5 long long ans;
 6 il int Min(it p,it q){
 7     return p<q?p:q;
 8 }
 9 int main(){
10     scanf("%d%d",&n,&k),ans=1ll*n*k;
11     for(it l=1,r;l<=n;l=r+1)
12         r=(k/l?Min(k/(k/l),n):n),ans=ans-1ll*(r-l+1)*(l+r)/2*1ll*(k/l); 
13     printf("%lld",ans);
14     return 0;
15 }
View Code

 

然后我们讲主题:P2260 [清华集训2012]模积和

由于我不会用LaTeX写数学公式,所以转一篇博文:戳这里 讲的非常清楚。

这里稍微提一下。

首先求逆元先分解质因数然后用a-1 mod p = aΦ(p)-1 mod p 去计算

然后就是把 i mod j 转化为 i-(i/j)*j 其中i/j由于c++的性质自动下取整

接着就是容斥原理把i!=j给消掉

然后整理一下式子,把剩下的往里面代。

一个小细节就是默认n<=m 如果读入的时候n>m就交换一下

 1 #include<cstdio>
 2 #define it register int
 3 #define il inline
 4 #define rll register long long
 5 typedef long long ll;
 6 typedef unsigned long long ull;
 7 typedef long double ldb;
 8 const long long p=19940417;
 9 ll inv,n,m,ans;
10 il ll mul(ll a,ll b){
11     return (a*b-(ull)((ldb)a/p*b+1e-7)*p+p)%p;
12 }
13 il void ksm(ll x,ll l){
14     inv=1;
15     while(l){
16         if(l&1) inv=mul(inv,x);
17         l>>=1,x=mul(x,x);
18     }
19 }
20 il ll sumsl(ll l,ll r){
21     return 1ll*(l+r)*(r-l+1)/2%p;
22 }
23 il ll sumn2(ll x){
24     return mul(mul(x,x+1),mul(x<<1|1,inv));
25 }
26 il ll rc(ll x){
27     ll now=0;
28     for(rll l=1,r;l<=x;l=r+1)
29         r=(x/(x/l)),now=(now+mul(x,r-l+1)-mul(sumsl(l,r),x/l)+p)%p;
30     return now;
31 }
32 il ll mol(ll x){
33     return x<0?x+p:(x>=p?x-p:x);
34 }
35 il ll Min(ll p,ll q){
36     return p<q?p:q;
37 }
38 int main(){
39     scanf("%lld%lld",&n,&m);
40     if(n>m) n+=m,m=n-m,n-=m;
41     ksm(6,17091779);ans=mul(rc(n),rc(m)); 
42     for(rll l=1,r,s1,s2,s3;l<=n;l=r+1){
43         r=Min(n/(n/l),m/(m/l));
44         s1=mul(mul(n,m),r-l+1);
45         s2=mul(mul(m/l,n/l),sumn2(r)-sumn2(l-1)+p);
46         s3=mul(mol(mul(n/l,m)+mul(m/l,n)),sumsl(l,r));
47         ans=mol(ans-mol(s1+s2-s3));
48     } 
49     printf("%lld",ans);
50     return 0;
51 }
52 //19940417= 2848631*7 phi(19940417)=17091779
View Code

 

posted @ 2019-10-11 10:02  kylin_xy  阅读(153)  评论(0编辑  收藏  举报