3.1 Problem Statement
小 D 正在研究集合。
小 D 想要知道,对于给定的 n,有多少个集合 {1, 2, · · · , n} 的子集满足最大公约
数为 1,而最小公倍数为 n。
但是小 D 并不会,请你帮帮他。因为答案可能很大,所以你只要输出这样的子集
个数对 998244353 取模的结果即可。
3.2 Input Format
从标准输入读入数据。
第一行一个整数 n,其含义见题目描述部分。
3.3 Output Format
向标准输出输出答案。
输出一行一个整数表示答案对 998244353 取模的结果。
3.4 Sample 1
1 Input
6
3.4.2 Output
7
3.4.3 Explanation
所有合法的子集为 {1, 6},{2, 3},{1, 2, 3},{1, 2, 6},{1, 3, 6},{2, 3, 6} 以及 {1, 2, 3, 6}。
3.5 Sample 2
见下发文件 subset/subset2.in 与 subset/subset2.ans。
3.6 Sample 3
见下发文件 subset/subset3.in 与 subset/subset3.ans。
3.7 Constraints
对于所有测试数据,1 ≤ n ≤ 1018。
• 子任务 1(30 分):n ≤ 20;
• 子任务 2(30 分):n ≤ 109;
• 子任务 3(20 分):n ≤ 1015。
• 子任务 4(20 分):无特殊限制。
题解:
首先,集合中只能包含n的约数。
所以,把n质因数分解。
同时,我们知道,对于某一个质因子,所选的数中必须包含0次和最高次。
但我也不知道怎么求。。。
所以考虑容斥。
且这道题较为特殊,普通的根号筛素数无法胜任,此时就要沿袭上一道题的优良传统 ,先筛除小于 n 3 \sqrt[3]n 3n的质因数,此时所剩的质数只有p,pq, p 2 p^{2} p2。
平方数很好判断。所需要的就只是判素数了。
此时我们可以用Miller_Brain算法。
部分代码来自网上。
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstdlib>
#include<ctime>
#define N 10000005
#define ll long long
using namespace std;
const long long Mod=998244353