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; }