1. 程式人生 > >2018沈陽網絡賽G

2018沈陽網絡賽G

nbsp namespace scan con eof while return == tor

容斥+狀壓

技術分享圖片
#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

2018沈陽網絡賽G