zoukankan      html  css  js  c++  java
  • P2260 [清华集训2012]模积和 【整除分块】

    一、题目

      P2260 [清华集训2012]模积和

    二、分析

      参考文章:click here

      具体的公式推导可以看参考文章。博主的证明很详细。

      自己在写的时候问题不在公式推导,公式还是能够比较顺利的推导出来,但是,码力不够,比如说在乘积的时候,因为输入时候的$n$和$m$没有注意,一直用的$int$类型的,导致中间结果早就爆了,自己却浑然不知。

      还有一个细节就是题目给的模数不是质数,所以求逆元的时候需要使用扩展欧几里得进行求解逆元。  

    三、AC代码

     1 #include <bits/stdc++.h>
     2 
     3 using namespace std;
     4 #define ll long long
     5 #define Min(a,b) ((a)>(b)?(b):(a))
     6 #define Max(a,b) ((a)>(b)?(a):(b))
     7 const int mod = 19940417;
     8 const int inv = 3323403;
     9 
    10 void exgcd(ll a, ll b, ll &x, ll &y)
    11 {
    12     if(b == 0)
    13     {
    14         x = 1, y = 0;
    15         return ;
    16     }
    17     else
    18     {
    19         ll x1, y1;
    20         exgcd(b, a % b, x1, y1);
    21         x = y1;
    22         y = x1 - (a / b) * y1;
    23     }
    24 }
    25 
    26 ll solve(ll n)
    27 {
    28     ll ans = (n % mod * n % mod) % mod;
    29     ll L = 1, R;
    30     for(L; L <= n; L = R + 1)
    31     {
    32         int k = n / L;
    33         if(!k)
    34         {
    35             R = n;
    36         }
    37         else
    38         {
    39             R = n / k;
    40         }
    41         ans = (ans - (R - L + 1) * (L + R) / 2 % mod * k % mod + mod) % mod;
    42     }
    43     return ans;
    44 }
    45 
    46 ll get(ll n)
    47 {
    48     return n * (n + 1) % mod * (n<<1|1) % mod * inv % mod;
    49 }
    50 
    51 int main()
    52 {
    53     //exgcd(6, mod, x, y);  //x就是6在mod下的逆元
    54     ll n, m;
    55     cin >> n >> m;
    56     ll ans1, ans2, ans3, ans = solve(n) * solve(m) % mod;
    57     if(n < m) swap(n, m);
    58     ll L, R;
    59     for(L = 1; L <= m; L = R + 1)
    60     {
    61         R = Min(n/(n/L), m/(m/L));
    62         ans1 = (n*m % mod *(R - L + 1)) % mod;
    63         ans2 = ((n/L) * m % mod + (m/L) * n % mod) % mod * ((R - L + 1) * (L + R) / 2 % mod) % mod;
    64         ans3 = ((n/L) * (m/L) % mod * (get(R) - get(L - 1) + mod) % mod )% mod;
    65         ans = ((ans - (ans1 + ans3 - ans2) ) % mod + mod) % mod;
    66     }
    67     printf("%lld
    ", ans%mod);
    68     return 0;
    69 }
  • 相关阅读:
    与客服聊天功能测试点
    京东优惠券如何测试
    Linux笔试题
    线程与线程池原理
    PyCharm 介绍、安装、入门使用
    银行APP测试用户体验性方面
    python的闭包
    列表解析2
    深入函数
    再谈装饰器@@@
  • 原文地址:https://www.cnblogs.com/dybala21/p/11244246.html
Copyright © 2011-2022 走看看