2018沈阳网络赛G

容斥+状压

 

 

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll MOD = 1e9+7;
#include<vector>
//const int MAX = 110;
const int N = 100000;
int arr[6000000];//p[N]用来存质数 
ll n;
int p;
vector<ll>v;
void getp(ll m, ll n) {  //分解质因子 
    p = 0;
    for(int i = 2; i <= n && i * i <= m; i++) {  
        if(m % i == 0) {  
            arr[p++] = i;
            while(m % i == 0)  
                m /= i;  
        }  
    }  
    if(m > 1) arr[p++] = m;
}
ll get(ll temp)
{
        ll sum_temp;
        sum_temp=1ll*(((1+n/temp)*(n/temp)/2)%MOD)*temp%MOD;
        sum_temp += 1ll*((((((n/temp)*((n/temp)+1)%MOD)*(2*(n/temp)+1))%MOD)*166666668)%MOD)*temp*temp%MOD;
        sum_temp=1ll*sum_temp%MOD;
        return sum_temp;
}

int main(){
    ll  m;
    while(scanf("%lld %lld", &n, &m) != EOF)
    {
        ll sum = 0;
        sum = 1ll*((n+1)*n/2)%MOD;
        sum += 1ll*((((n*(n+1)%MOD)*(2*n+1))%MOD)*166666668)%MOD;
        sum= 1ll*sum%MOD;
        getp(m, n);
    //    cout<<p<<" "<<sum<<endl;
        ll ans = 0;
        for(int i = 1; i < (1 << p); i++) { //状压 
            ll res = 0, cnt = 1;
            for(int j = 0; j < p; j++) {
                if(i & (1 << j)) {
                    cnt *= arr[j];
                    res++;
                }
            }
            if(res & 1) ans += get(cnt); //容斥 
            else ans -= get(cnt);
            ans = (ans + MOD)%MOD;
        //    cout<<ans<<endl;
        }
        sum = (sum - ans + MOD)%MOD;
        printf("%lld\n",sum );
    }
    return 0;
}
View Code

 

转载于:https://www.cnblogs.com/LMissher/p/9610856.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值