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

猜你喜欢

转载自www.cnblogs.com/LMissher/p/9610856.html
今日推荐