• 数论-整除分块


    好久没碰数论的东西了,已经完全生疏了。

    做了几道数论题总结一下。

    余数求和

    大意:
    求 \sum_{i=1}^{n}k%i

    思路:
    隐约记得哪次比赛做过原题,也做出来了,但是现在还是有点懵了。。。

    先把式子转化一下吧

    \sum_{i=1}^{n}k%i= \sum_{i=1}^{n}k-\left \lfloor k/i \right \rfloor\doteq n*k-\sum_{i=1}^{n}i*\left \lfloor k/i \right \rfloor

    那么整个式子就稍微有点样子了。

    接下来对每一个l求对应的r

    t=\left \lfloor k/l \right \rfloor

    r=max(i),i*t<=n;

    得到:

    r=k/t;

    这是对于每一个l对应的r,对于\sum里面的i*\left \lfloor k/i \right \rfloor,i在连续的区间里是一个等差数列,那么直接套公式即可。

    1. #include<bits/stdc++.h>
    2. using namespace std;
    3. #define ll long long
    4. #define mx *max_element
    5. const ll N=2e5+10;
    6. ll n,k,r;
    7. int main()
    8. {ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
    9. cin>>n>>k;
    10. ll ans=n*k;
    11. for(int l=1;l<=n;l=r+1)
    12. {
    13. ll t=k/l;
    14. if(t!=0) r=min(k/t,n);
    15. else r=n;
    16. ans-=t*(r-l+1)*(l+r)/2;
    17. }
    18. cout<<ans<<endl;
    19. return 0;
    20. }

    虽然是一道省选-,但代码是真的短。

    calculating

    大意:

    思路:
    首先,这个\prod_{i=1}^{n}ki就是求\sigma (n),也就是我们所熟知的求数字约数的函数,换句话说,这里f(x)=\sum_{i=1}^{n}\sum_{d|i}^{}1,其中\sum_{d|i}1=\sigma (i).

    不妨做一个转换,改为先枚举d,则

    f(x)=\sum_{i=1}^{n}\sum_{d|i}^{}1=\sum_{d=1}^{n}\left \lfloor n/d \right \rfloor,

    到这一步,要求f(x)那就是轻而易举了。

    最后,由于i是从l到r,那么\sum_{i=l}^{r}f(x)=\sum_{i=1}^{r}f(x)-\sum_{i=1}^{l-1}f(x),这样的话写一个函数就好了。

    1. #include<bits/stdc++.h>
    2. using namespace std;
    3. #define ll long long
    4. const ll mod=998244353;
    5. ll a,b;
    6. ll f(ll x)
    7. {
    8. ll ans=0;
    9. ll l,r;
    10. for(ll l=1;l<=x;l=r+1)
    11. {
    12. r=x/(x/l);
    13. ans=(ans+(x/l)*(r-l+1)%mod)%mod;
    14. }
    15. return ans%mod;
    16. }
    17. int main()
    18. {
    19. cin>>a>>b;
    20. cout<<(f(b)-f(a-1)+mod)%mod<<endl;
    21. return 0;
    22. }

    点是有点多,但都想到了就挺板的。

    模积和

    大意:

    思路:
    这里有一个限制是i!=j,所以不妨把式子转化一下。

    \sum_{i=1}^{n}\sum_{j=1}^{m}n%i*m%j(i\neq j)=\sum_{i=1}^{n}\sum_{j=1}^{m}(n%i)*(m%j)-\sum_{i=1}^{n}(n%i)*(m%i)

     其中\sum_{i=1}^{n}\sum_{j=1}^{m}(n%i)*(m%j)=\sum_{i=1}^{n}n%i*\sum_{j=1}^{m}m%j

    这个就是我们在第一个问题里讨论的东西,那应该就很好处理了。

    然后是后面的东西,如果展开的话:

    \sum_{i=1}^{n}(n%i)*(m%i)=\sum_{i=1}^{n}(n-i*\left \lfloor n/i \right \rfloor)*(m-i*\left \lfloor m/i \right \rfloor)

    =\sum_{i=1}^{n}n*m-m*i*\left \lfloor n/i \right \rfloor-n*i*\left \lfloor m/i \right \rfloor+i*i*\left \lfloor n/i \right \rfloor*\left \lfloor m/i \right \rfloor

    这里的第一项就不用说了,第二三项其实跟上面讨论的\sum_{i=1}^{n}n%i=\sum_{i=1}^{n}n-i*\left \lfloor n/i \right \rfloor是一个道理,只是加了一个常数而已。

    那么最后一项,i*i*\left \lfloor n/i \right \rfloor*\left \lfloor m/i \right \rfloor,与上一个的区别只是i的次数提高了一项,但如果照搬之前的思路,求等差数列的和的话,\sum i^{^{2}}=n*(n+1)*(2n+1)/6,那么这一项也解决了,那么整个题目到这里也就ok了。

    还想说一个坑点,就是题目里这个取模的数居然不是质数。。。

    也怪我傻,998244353,1e9+7见多了,看啥都像质数

    所以这里的逆元得自己提前去求好了,不能用快速幂。

    1. #include<bits/stdc++.h>
    2. using namespace std;
    3. #define ll long long
    4. const ll mod=19940417;
    5. const ll inv2=9970209;
    6. const ll inv6=3323403;
    7. #define endl '\n'
    8. ll n,m;
    9. ll sd(ll x)
    10. {
    11. return x*(x+1)%mod*(2*x+1)%mod*inv6%mod;
    12. }
    13. ll sdd(ll x)
    14. {
    15. return x*(x+1)%mod*inv2%mod;
    16. }
    17. ll f(ll n)//求sum(n-(n/i)*i)
    18. {
    19. ll sum=n*n%mod;
    20. //cout<<sum<<endl;
    21. for(ll l=1,r;l<=n;l=r+1)
    22. {
    23. ll t=n/l;
    24. r=n/t;
    25. sum=(sum-t*(sdd(r)-sdd(l-1)+mod)%mod+mod)%mod;
    26. //cout<<sum<<endl;
    27. }
    28. return sum;
    29. }
    30. int main()
    31. {
    32. cin>>n>>m;
    33. //cout<<sdd(4)<<' '<<sdd(3)<<endl;
    34. //cout<<f(n)<<" "<<f(m)<<endl;
    35. ll sum=0,ans=0;
    36. sum=(sum+f(n))%mod;
    37. sum=(sum*f(m))%mod;
    38. ans=sum;sum=0;
    39. for(ll l=1,r;l<=min(n,m);l=r+1)
    40. {
    41. r=min(n/(n/l),m/(m/l));
    42. sum+=(r-l+1+mod)%mod*n%mod*m%mod;
    43. sum-=(r-l+1+mod)%mod*(l+r)%mod*((n/l)*m%mod+(m/l)*n%mod)%mod*inv2%mod;
    44. sum+=(sd(r)-sd(l-1)+mod)%mod*(n/l)%mod*(m/l)%mod;
    45. sum=(sum+mod)%mod;
    46. }
    47. cout<<(ans-sum+mod)%mod<<endl;
    48. return 0;
    49. }

    大致就先这样,后面可能会补新的题 

  • 相关阅读:
    STM32玩转物联网实战篇:5.ESP8266 WIFI模块MQTT通信示例详解
    GO结构体
    探索“吴家路径”:一条带动村民共同富裕,有效促乡村善安治之路
    java计算机毕业设计专业主任排课系统源码+数据库+系统+lw文档+mybatis+运行部署
    合并单元格
    神经网络建模的基本思想,三维建模神经网络设计
    【Linux】第四站:Linux基本指令(三)
    靠着腾讯的「操作系统笔记」,成功帮我拿下了 3 个大厂的 offer
    数据结构—内部排序(上)
    Java实现Fisher‘s Exact Test 的置信区间的计算
  • 原文地址:https://blog.csdn.net/sophilex/article/details/125510519