ACM-ICPC 2018 沈阳赛区网络预赛 G 容斥原理

https://nanti.jisuanke.com/t/31448

解析 易得an=n*n+n O(1)得到前n项和  再删除与m不互素的数  我们用欧拉函数求出m的质因数  枚举其集合的子集 进行容斥

n*n+n+2n*2n+2n+3n*3n+3n=(1+4+9)*n*n+(1+2+3)*n 所以也可以O(1)得到。

AC代码

#include <bits/stdc++.h>
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define all(a) (a).begin(), (a).end()
#define fillchar(a, x) memset(a, x, sizeof(a))
#define huan printf("\n");
#define debug(a,b) cout<<a<<" "<<b<<" ";
using namespace std;
const int maxn=1e5+100,inf=0x3f3f3f3f;
typedef long long ll;
typedef pair<int,int> pii;
const ll mod=1e9+7;
int yin[maxn],cnt;
void euler(ll n)  //返回euler(n)
{
    ll res=n,a=n;
    cnt=0;
    for(ll i=2; i*i<=a; i++)
    {
        if(a%i==0)
        {
            yin[cnt++]=i;
            res=res/i*(i-1);//先进行除法是为了防止中间数据的溢出 爆int
            while(a%i==0)
                a/=i;
        }
    }
    if(a>1)
        res=res/a*(a-1),yin[cnt++]=a;
}
ll powmod(ll n,ll m)
{
    ll ans=1;
    while(m>0)
    {
        if(m&1)
            ans=ans*n%mod;
        m = m>>1;
        n = n*n%mod;
    }
    return ans;
}
ll inv2=powmod(2,mod-2);
ll inv6=powmod(6,mod-2);
ll getsum1(ll n)
{
    return n*(n+1)%mod*(2*n%mod+1)%mod*inv6%mod;
}
ll getsum2(ll n)
{
    return n*(n+1)%mod*inv2%mod;
}
int main()
{
    ll n,m;
    while(scanf("%lld%lld",&n,&m)!=EOF)
    {
        euler(m);
        ll ans=(getsum1(n)+getsum2(n))%mod;
        for(int i=0; i<(1<<cnt); i++)
        {
            ll temp=1,jishu=0;
            for(int j=0; j<cnt; j++)
            {
                if(i&(1<<j))
                    temp*=yin[j],jishu++;
            }
            if(temp==1)continue;
            ll bei=n/temp;
            ans=(ans+powmod(-1,jishu)*temp*temp%mod*getsum1(bei)%mod+mod)%mod;
            ans=(ans+powmod(-1,jishu)*temp*getsum2(bei)%mod+mod)%mod;
        }
        printf("%lld\n",ans);
    }
}

 

posted @ 2018-09-12 22:09  灬从此以后灬  阅读(188)  评论(0编辑  收藏  举报