[NOIP模拟] Heal
Description
其题的大意类似于 POJ 1091。
Input
给出N,M
Output
输出答案 mod 1e9 + 7
Solution:
表示在读了很久的题之后的发现这就是一个加强版的跳蚤,于是打算直接写就可以了,但是在考场上我居然写不来容斥,好,我是蒟蒻,我是傻逼。
我就讲讲容斥,来纪念这次傻逼的 WA,这道题解法与 POJ 1091 跳蚤 类似,我这里就简单讲一讲。
我们只需要考虑
GCD
为 1 的总数,那么就求
GCD
不为 1 的,我们很容易就想到把当前数质因数分解,然后我们
DFS
(我记住了),
DFS(int x,int y,int z)
分别表示为当前处理第 x 位的质因数,已经选了 y 个数, 当期选的数的总积为 z, DFS 的下层为
DFS(x+1,y,z)
和
DFS(x+1,y+1,z∗prime[x])
,注意题目数据范围,很恶心。
Code:
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
#include <algorithm>
#include <iostream>
#include <cmath>
#include <ctime>
#include <map>
#include <vector>
#define UL unsigned long long
using namespace std;
inline UL read() {
UL i = 0, f = 1;
char ch = getchar();
while(!isdigit(ch)) {
if(ch == '-') f = -1; ch = getchar();
}
while(isdigit(ch)) {
i = (i << 3) + (i << 1) + (UL)(ch - '0'); ch = getchar();
}
return i * f;
}
const int MAXN = 120;
const int mod = 1e9 + 7;
UL prime[MAXN], n, m, ans;
int tail;
inline UL ksm(UL a, UL b) {
UL ret = 1; a %= mod;
while(b) {
if(b & 1) ret = ret * a % mod;
b >>= 1;
a = a * a % mod;
}
return ret;
}
inline void dfs(int x, int y, UL z) {
if(z > m) return ;
if(x == tail + 1) {
if(y) {
if(y & 1) ans = (ans - ksm((UL)m / z, n) + mod) % mod;
else ans = (ans + ksm((UL)m / z, n)) % mod;
}
return ;
}
dfs(x + 1, y, z);
dfs(x + 1, y + 1, (UL)z * prime[x]);
}
int main() {
n = read(), m = read();
UL now = m;
tail = 0;
for(int i = 2; (UL)i * i <= m; ++i)
if(now % i == 0) {
prime[++tail] = (UL)i;
now /= i;
while(now % i == 0)
now /= i;
}
if(now > 1) prime[++tail] = now;
ans = ksm(m, n);
dfs(1, 0, 1);
cout<<ans % mod;
}