• 【题解】P2260 [清华集训2012]模积和(数学,整除分块)


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

    比较简单的一道推式子的题。(清华集训居然会出这种水题的吗)

    题目链接

    P2260 [清华集训2012]模积和

    题意概述

    i=1nj=1m(nmodi)×(mmodj),ij" role="presentation" style="text-align: center; position: relative;">i=1nj=1m(nmodi)×(mmodj),ij

    mod19940417" role="presentation" style="position: relative;">mod19940417 的值

    思路分析

    直接容斥一下然后推式子即可,见下:

    i=1nj=1m(nmodi)(mmodj)=i=1n(nmodi)j=1m(mmodj)i=1min(n,m)(nmodi)(mmodj)=i=1n(nmodi)j=1m(mmj×j)i=1min(n,m)(nni×i)(mmi×i)=i=1n(nmodi)(j=1mmj=1mmj×j)i=1min(n,m)(nmnmi×imni×i+mini×i2)=i=1n(nmodi)(m2j=1mmj×j)i=1min(n,m)nm+ni=1min(n,m)mi×i+mi=1min(n,m)ni×ii=1min(n,m)nimi×i2=(m2j=1mmj×j)i=1n(nmodi)min(n,m)nm+ni=1min(n,m)mi×i+mi=1min(n,m)ni×ii=1min(n,m)nimi×i2=(m2j=1mmj×j)(n2i=1nni×i)min(n,m)nm+ni=1min(n,m)mi×i+mi=1min(n,m)ni×ii=1min(n,m)nimi×i2" role="presentation" style="position: relative;">i=1nj=1m(nmodi)(mmodj)=i=1n(nmodi)j=1m(mmodj)i=1min(n,m)(nmodi)(mmodj)=i=1n(nmodi)j=1m(mmj×j)i=1min(n,m)(nni×i)(mmi×i)=i=1n(nmodi)(j=1mmj=1mmj×j)i=1min(n,m)(nmnmi×imni×i+mini×i2)=i=1n(nmodi)(m2j=1mmj×j)i=1min(n,m)nm+ni=1min(n,m)mi×i+mi=1min(n,m)ni×ii=1min(n,m)nimi×i2=(m2j=1mmj×j)i=1n(nmodi)min(n,m)nm+ni=1min(n,m)mi×i+mi=1min(n,m)ni×ii=1min(n,m)nimi×i2=(m2j=1mmj×j)(n2i=1nni×i)min(n,m)nm+ni=1min(n,m)mi×i+mi=1min(n,m)ni×ii=1min(n,m)nimi×i2

    发现前四项都可以整除分块随便求。

    我们考虑最后一项怎么求。

    首先考虑 i=1min(n,m)nimi" role="presentation" style="position: relative;">i=1min(n,m)nimi,这实际上也可以整除分块,只不过需要二维整除分块。

    其实它和一般的整除分块区别也不大,很显然,每次只需要改一下块长就好了。

    具体地,每次求 r" role="presentation" style="position: relative;">r 时:

    r=min(nnl,mml)" role="presentation" style="text-align: center; position: relative;">r=min(nnl,mml)

    时间复杂度是 O(min(n,m))" role="presentation" style="position: relative;">O(min(n,m))

    然后考虑 i=1min(n,m)i2" role="presentation" style="position: relative;">i=1min(n,m)i2 怎么求。

    有一个结论:

    12+22+32++n2=n(n+1)(2n+1)6" role="presentation" style="text-align: center; position: relative;">12+22+32++n2=n(n+1)(2n+1)6

    所以我们就可以求出整个的式子了。

    易错点

    19940417" role="presentation" style="position: relative;">19940417 不是素数,所以请注意:

    模意义下计算 x" role="presentation" style="position: relative;">x 的逆元只有当 mod" role="presentation" style="position: relative;">mod 为素数时才能使用 qpow(x,mod2)" role="presentation" style="position: relative;">qpow(x,mod2)!!!

    模意义下计算 x" role="presentation" style="position: relative;">x 的逆元只有当 mod" role="presentation" style="position: relative;">mod 为素数时才能使用 qpow(x,mod2)" role="presentation" style="position: relative;">qpow(x,mod2)!!!

    模意义下计算 x" role="presentation" style="position: relative;">x 的逆元只有当 mod" role="presentation" style="position: relative;">mod 为素数时才能使用 qpow(x,mod2)" role="presentation" style="position: relative;">qpow(x,mod2)!!!

    我是不会告诉你我在这挂了一个小时的……

    所以可以使用 exgcd 预处理出来 2" role="presentation" style="position: relative;">26" role="presentation" style="position: relative;">6逆元,然后求解。

    代码实现

    1. //luoguP2260
    2. #include
    3. #include
    4. #include
    5. #define int long long
    6. using namespace std;
    7. const int mod=19940417,inv2=9970209,inv6=3323403;
    8. inline int read()
    9. {
    10. int x=0,f=1;char ch=getchar();
    11. while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    12. while(ch>='0'&&ch<='9'){x=x*10+ch-48;ch=getchar();}
    13. return x*f;
    14. }
    15. int qpow(int a,int T)
    16. {
    17. int ret=1;
    18. while(T)
    19. {
    20. if(T&1)(ret*=a)%=mod;
    21. (a*=a)%=mod;T>>=1;
    22. }
    23. // cout<
    24. return ret;
    25. }
    26. int work(int n,int k)
    27. {
    28. int ret=0;
    29. for(int l=1,r;l<=n;l=r+1)
    30. {
    31. if(k/l==0)break;
    32. r=min(k/(k/l),n);
    33. (ret+=(k/l)*(l+r)%mod*(r-l+1)%mod*inv2)%=mod;
    34. }
    35. return ret;
    36. }
    37. int get(int n)
    38. {
    39. return n*(n+1)%mod*(2*n+1)%mod*inv6%mod;
    40. }
    41. int work2(int n,int k,int p)
    42. {
    43. int ret=0;
    44. for(int l=1,r;l<=n;l=r+1)
    45. {
    46. r=min({k/(k/l),p/(p/l),n});
    47. (ret+=(k/l)*(p/l)%mod*(get(r)-get(l-1)+mod)%mod)%=mod;
    48. }
    49. return ret;
    50. }
    51. signed main()
    52. {
    53. int n,m;
    54. n=read();m=read();
    55. int sumn=work(n,n),summ=work(m,m);
    56. int sumM=work(min(n,m),m),sumN=work(min(n,m),n);
    57. int ans1=(n*n%mod-sumn+mod)%mod*(m*m%mod-summ+mod)%mod;
    58. int ans2=(min(n,m)*n%mod*m%mod+mod)%mod;
    59. int ans3=n*sumM%mod;
    60. int ans4=m*sumN%mod;
    61. int ans5=work2(min(n,m),n,m);
    62. cout<<((((ans1-ans2+mod)%mod+ans3)%mod+ans4)%mod-ans5+mod)%mod<<"\n";
    63. return 0;
    64. }
  • 相关阅读:
    csapp-attacklab(完美解决版)
    ES6新特性
    [附源码]计算机毕业设计springboot校园商铺
    2022 春节抖音视频红包系统设计与实现
    如何通过手机自学编程入门:探索四、五、六、七方面的学习路径
    常用设计模式
    [剑指 Offer 28]对称的二叉树
    【无百度智能云与实体经济“双向奔赴”: 一场1+1>2的双赢 标题】
    torchnet简介
    mPEG-DMPE 甲氧基-聚乙二醇-双肉豆蔻磷脂酰乙醇胺用于形成隐形脂质体
  • 原文地址:https://blog.csdn.net/m0_46222454/article/details/127812994