zoukankan      html  css  js  c++  java
  • P2260 [清华集训2012]模积和

    P2260 [清华集训2012]模积和

    整除分块+逆元

    详细题解移步P2260题解板块

    式子可以拆开分别求解,具体见题解

    这里主要讲的是整除分块(数论分块)mod不为素数时如何求逆元

    整除分块:求Σ「n/i」(i=1~n),「」表示向下取整

    由于「n/i」在某段区间内都有相同的值,所以可以分块算,复杂度O( sqrt(n) )

    code:

    ll res=0;
    for(ll l=1,r;l<=n;l=r+1){
      r=n/(n/l);
      res=res+(r-l+1)*(n/l);
    }
    return
    res;

    当mod是素数时,我们可以用费马小定理直接算,但是mod不为素数时,我们就可以用欧拉函数算(定义等右转Baidu)

    当n,p互素时,n在 mod p 下的乘法逆元为 n^(phi(p)-1)

    当n,p不互素时,并没有乘法逆元233333

    特别地,当p为素数时,phi(p)=p-1,恰好是费马小定理

    本人能力限制,不给出证明(逃

    当所求逆元的数事先指定时,可以用暴力法(比如本题只需求2,6的逆元)

    下面给出暴力法和欧拉函数的code:

    #include<bits/stdc++.h>
    using namespace std;
    const int mod=19940417;
    template <typename T> int find_inv(T x){ //暴力预求
        for(int i=1;i<=71806291;++i) //自行规定范围
            if(1LL*x*i%mod==1) //根据定义
                return i;
    }
    template <typename T> int _phi(T x){ //欧拉函数计算
        int k=sqrt(x),phi=x;
        for(int i=2;i<=k;++i)
            if(x%i==0){
                phi=phi/i*(i-1);
                while(x%i==0) x/=i;
            }
        if(x>1) phi=phi/x*(x-1);
        return phi;
    }
    int ksm(int x,int y){
        int res=1;
        for(;y;y>>=1){
            if(y&1) res=1LL*res*x%mod;
            x=1LL*x*x%mod;
        }return res;
    }
    int main(){
        cout<<find_inv(2)<<" "<<find_inv(6)<<endl;
        int phi=_phi(mod);
        cout<<ksm(2,phi-1)<<" "<<ksm(6,phi-1);
        //2->9970209 6->3323403
        return 0;
    }

    接下来就是本题的code了

    #include<iostream>
    #include<cstdio>
    using namespace std;
    typedef long long ll;
    template <typename T> inline T min(T &a,T &b) {return a<b ?a:b;}
    const int mod=19940417;
    ll n,m,ans;
    inline ll sum1(ll l,ll r) {return (l+r)*(r-l+1)%mod*9970209%mod;} //求等差数列
    inline ll sum2(ll x) {return x*(x+1)%mod*(x*2+1)%mod*3323403%mod;} //求1^2+2^2+3^2+...+x^2
    inline ll calc(ll x){ //整除分块(根据题意稍作修改)
        ll res=0;
        for(ll l=1,r;l<=x;l=r+1) r=x/(x/l),res=(res+(r-l+1)*x-sum1(l,r)*(x/l)+mod)%mod;
        return res;
    }
    int main(){
        scanf("%lld%lld",&n,&m); if(n>m) swap(n,m);
        ans=calc(n)*calc(m)%mod; ll s1,s2,s3;
        for(ll l=1,r;l<=n;l=r+1){
            r=min(n/(n/l),m/(m/l));
            s1=n*m%mod*(r-l+1)%mod;
            s2=(n/l*m+m/l*n)%mod*sum1(l,r)%mod;
            s3=(n/l)*(m/l)%mod*(sum2(r)-sum2(l-1)+mod)%mod;
            ans=(ans-(s1-s2+s3+mod)%mod+mod)%mod; //式子拆分后分别求解
        }printf("%lld",ans);
        return 0;
    }
  • 相关阅读:
    csp2020游记
    agc006_f Blackout
    CF1368G Shifting Dominoes
    AtCoder Grand Contest 009 简要题解
    Codeforces Round #666 (Div. 1)
    CSP 2019 树的重心
    Luogu-P4859 已经没什么好害怕的了
    2020.9.17 校内测试
    CF379F New Year Tree
    图论(小结论)
  • 原文地址:https://www.cnblogs.com/kafuuchino/p/9683217.html
Copyright © 2011-2022 走看看