Spare Tire

题目链接

//题目大意:输入n,m,zhao找出1~n中与m互质的的数,将这些数当作a数组的下标,求和;

//思路:打表得出,a[i]=i*i+i;

质因数不超过10个,所以先找出m的质因数,然后找出1~n中与m不互质的的数,容斥一下,得出答案

#include<cstdio>
#include<algorithm>
#include<iostream>
#include<vector>
using namespace std;
typedef long long ll;
long long inv6;
long long inv2;
ll n,m;
const ll mod=1e9+7;
vector<ll>x;//用来存储m的质因数;
ll Qpow(ll a,ll b)
{
    ll ans=1;
    while(b)
    {
        if(b%2==1)ans=ans*a%mod;
        a=a*a%mod;
        b=b>>1;
    }
    return ans%mod;
}
void f1(ll m)
{
    for(ll i=2;i*i<=m;i++)
    {
        if(m%i==0)
        {
            x.push_back(i);
            while(m%i==0)
                m=m/i;
        }
    }
    if(m>1)x.push_back(m);
    return ;
}
ll NN(ll n)//n^2求和公式,n*(1+n)*(2*n+1)/6;因为n*(n+1)*(2*n+1)模完之后,不一定能被6整除,所以乘以inv6;
{
    inv6=Qpow(6,mod-2);
    ll ans=n*(n+1)%mod;
    ans=ans*(2*n+1)%mod*inv6%mod;
    return ans%mod;
}
ll N(ll n)//n的求和公式n*(n+1)/2;
{
    inv2=Qpow(2,mod-2);
    ll ans=(1+n)*n%mod;
    ans=ans*inv2%mod;
    return ans%mod;
}
int main()
{
    while(~scanf("%lld%lld",&n,&m))
    {
        ll sum=0,sum1=0;
        sum=NN(n)+N(n);
        x.clear();
        f1(m);
        ll len=x.size();
        for(int i=1;i<(1<<len);i++)
        {
            ll temp=1;
            int cn=0;
            for(ll j=0;j<len;j++)
            {
                if(i&(1<<j))
                {
                    temp*=x[j];
                    cn++;
                }
            }
            ll num=n/temp;
            ll sum2=NN(num)*temp%mod*temp%mod+N(num)*temp%mod;
            if(cn%2==1)sum1=(sum1+sum2)%mod;
            else sum1=(sum1-sum2+mod)%mod;

        }
        ll ans=(sum-sum1+mod)%mod;
        printf("%lld\n",ans);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_37378303/article/details/82624199