zoukankan      html  css  js  c++  java
  • ACM-ICPC 2018 沈阳赛区网络预赛 G.Spare Tire (容斥)

    ai

    题意:给出a的递推式,1到n中与m互质的数为i,求a[i]的和

    思路:得到a的通项公式为n^2+n,Sn的通项为n*(n+1)*(2n+1)/6+n*(n+1)/2,与m不互质的数,是取m的素因子的乘积,那么将m分解质因数,通过容斥原理,就可以得到与m不互质的数,总和减去这些数对应的a的和就是答案了。在求这些不互质数对应a的总和的时候,如果一个一个求会超时,需要直接求和。比如存在一个素因子是k,那么需要求下标为k,2k,3k,4k……的a的和,即求(kn)^2+kn通项的求和,为k^2*n*(n+1)*(2n+1)/6+k*n*(n+1)/2,项数为n/k。

    #include <bits/stdc++.h>
    using namespace std;
    #define ll long long
    #define mod 1000000007
    ll prime[10100];
    int pl=0;
    bool vis[10100];
    ll n,m;
    void getprime()
    {
        for(ll i=2;i<10010;i++)
        {
            if(vis[i]==false)
            {
                prime[++pl]=i;
            }
            for(int j=1;j<=pl&&i*prime[j]<10010;j++)
            {
                vis[i*prime[j]]=true;
                if(i%prime[j]==0)
                break;
            }
        }
    }
    ll num[15];
    int tot;
    void bre(ll n)//对n分解质因数
    {
        tot=0;
        for(int i=1;i<=pl&&prime[i]*prime[i]<=n;i++)
        {
            if(n%prime[i]==0)
            {
                num[tot++]=prime[i];
                while(n%prime[i]==0)
                {
                    n/=prime[i];
                }
            }
            if(n==1)
            break;
        }
        if(n!=1)
        {
            num[tot++]=n;
        }
    }
    ll inv2,inv3,inv6;
    ll fpow(ll a,ll b)//快速幂
    {
        ll ans=1;
        ll tmp=a%mod;
        while(b)
        {
            if(b&1)
            ans=ans*tmp%mod;
            tmp=tmp*tmp%mod;
            b>>=1;
        }
        return ans;
    }
    void solve()//用二进制实现容斥原理
    {
        ll ans=0;
        for(int i=0;i<(1<<tot);i++)//容斥定理所有的关系最多为2^tot
        {
            int cnt=0;
            ll sum=1;
            for(int j=0;j<tot;j++)//循环prime中的每一个运算
            {
                if(i&(1<<j))//要掌握&运算,与i的二进制的第j位比较,看是否为1,是则选中
                {
                    cnt++;//记录prime中的每个元素
                    sum*=num[j];
                }
            }
            ll k=n/sum;
            sum%=mod;
            ll p=(1+k)*k%mod*inv2%mod*sum%mod;
            ll q=k*(k+1)%mod*(2*k+1)%mod*inv6%mod*sum%mod*sum%mod;
            if(cnt&1)
            {
                ans-=p;
                if(ans<0)
                    ans+=mod;
                ans-=q;
                if(ans<0)
                    ans+=mod;
            }
            else
            {
                ans=(ans+p);
                if(ans>mod)
                    ans-=mod;
                ans+=q;
                if(ans>mod)
                    ans-=mod;
            }
        }
        printf("%lld
    ",ans);
                
    
    }
    int main()
    {
        getprime();
        inv2=fpow(2,mod-2);
        inv6=fpow(6,mod-2);
        while(scanf("%lld%lld",&n,&m)!=EOF)
        {
            bre(m);
            solve();
        }
    }
  • 相关阅读:
    PHP读写XML文件的四种方法
    如何在linux系统中设置静态ip地址
    Memcached和Memcache安装(64位win7)
    Mysql存储过程和函数区别介绍
    随笔
    Vue 中使用axios传参数,后端收不到数据
    vs2019创建mvc连接mysql
    dapper多表查询
    Java并发编程:volatile关键字解析
    Mysql Innodb 间隙锁浅析
  • 原文地址:https://www.cnblogs.com/Fy1999/p/9629983.html
Copyright © 2011-2022 走看看