传送门

题意:

统计\(k\)元组个数\((a_1,a_2,\cdots,a_n),1\leq a_i\leq n\)使得\(gcd(a_1,a_2,\cdots,a_k,n)=1\)。

定义\(f(n,k)\)为满足要求的\(k\)元组个数,现在要求出\(\sum_{i=1}^n f(i,k),1\leq n\leq 10^9,1\leq k\leq 1000\)。

思路:

首先来化简一下式子,题目要求的就是:

\[\begin{aligned}
&\sum_{i=1}^n\sum_{j=1}^n\cdots \sum_{k=1}^n gcd(i,j,\cdots, k,n)=1\\
=&\sum_{i=1}^n\sum_{j=1}^n\cdots \sum_{k=1}^n\sum_{d|i,j,\cdots,k,n}\mu(d)\\
=&\sum_{d|n}\mu(d)\sum_{i=1}^{\frac{n}{d}}\sum_{j=1}^{\frac{n}{d}}\cdots \sum_{k=1}^\frac{n}{d}1\\
=&\sum_{d|n}\mu(d) (\frac{n}{d})^k
\end{aligned}
\]

套路到此结束~然后观察到这个式子其实是一个狄利克雷卷积的形式,\(f(i)=\mu(i),g(i)=i^k\),上式则为:\(f*g_{(n)}\)。

那么题目要求的就是这个卷积的前缀和,注意两个积性函数的卷积也是积性函数,因为\(\mu*I=\varepsilon\),所以我们再构造一个积性函数\(h=I\),直接上杜教筛就行了。最后的式子是:

\[h(1)\cdot S(n) = \sum_{i=1}^ng(i)-\sum_{d=2}^n h(d)S(\lfloor\frac{n}{d}\rfloor)
\]

后半部分直接整除分块,至于\(\sum_{i=1}^ng(i)\),拉格朗日插值能在\(O(k)\)的时间复杂度解决。

代码如下(比赛的时候写得稍微有点乱):

/*
* Author: heyuhhh
* Created Time: 2019/11/29 21:03:32
*/
#include <iostream>
#include <algorithm>
#include <vector>
#include <cmath>
#include <set>
#include <map>
#include <iomanip>
#define MP make_pair
#define fi first
#define se second
#define sz(x) (int)(x).size()
#define all(x) (x).begin(), (x).end()
#define INF 0x3f3f3f3f
#define Local
#ifdef Local
#define dbg(args...) do { cout << #args << " -> "; err(args); } while (0)
void err() { std::cout << '\n'; }
template<typename T, typename...Args>
void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
#else
#define dbg(...)
#endif
void pt() {std::cout << '\n'; }
template<typename T, typename...Args>
void pt(T a, Args...args) {std::cout << a << ' '; pt(args...); }
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
//head
const int N = 1e4 + 5, MOD = 998244353; int n, k;
ll qpow(ll a, ll b) {
ll ans = 1;
while(b) {
if(b & 1) ans = ans * a % MOD;
a = a * a % MOD;
b >>= 1;
}
return ans;
}
struct Lagrange {
static const int SIZE = 1005;
ll f[SIZE], fac[SIZE], inv[SIZE], pre[SIZE], suf[SIZE];
int n;
inline void add(ll &x, int y) {
x += y;
if(x >= MOD) x -= MOD;
}
void init(int _n) {
n = _n;
fac[0] = 1;
for (int i = 1; i < SIZE; ++i) fac[i] = fac[i - 1] * i % MOD;
inv[SIZE - 1] = qpow(fac[SIZE - 1], MOD - 2);
for (int i = SIZE - 1; i >= 1; --i) inv[i - 1] = inv[i] * i % MOD;
//设置f初值,可以根据需要修改
f[0] = 0;
for (int i = 1; i <= n; ++i)
f[i] = (f[i - 1] + qpow(i, k)) % MOD;
}
ll calc(ll x) {
if (x <= n) return f[x];
pre[0] = x % MOD;
for (int i = 1; i <= n; ++i) pre[i] = pre[i - 1] * ((x - i) % MOD) % MOD;
suf[n] = (x - n) % MOD;
for (int i = n - 1; i >= 0; --i) suf[i] = suf[i + 1] * ((x - i) % MOD) % MOD;
ll res = 0;
for (int i = 0; i <= n; ++i) {
ll tmp = f[i] * inv[n - i] % MOD * inv[i] % MOD;
if (i) tmp = tmp * pre[i - 1] % MOD;
if (i < n) tmp = tmp * suf[i + 1] % MOD;
if ((n - i) & 1) tmp = MOD - tmp;
add(res, tmp);
}
return res;
}
}lagrange;
int mu[N], p[N];
bool chk[N];
int pre[N];
void init() {
mu[1] = 1;
int cnt = 0;
for(int i = 2; i <= N - 1; i++) {
if(!chk[i]) p[++cnt] = i, mu[i] = -1;
for(int j = 1; j <= cnt && i * p[j] <= N - 1; j++) {
chk[i * p[j]] = 1;
if(i % p[j] == 0) {mu[i * p[j]] = 0; break;}
mu[i * p[j]] = -mu[i];
}
}
for(int i = 1; i <= N - 1; i++) {
int res = 0;
for(int j = 1; 1ll * j * j <= i; j++) {
if(i % j == 0) {
int d1 = j, d2 = i / j;
res = (res + 1ll * mu[d1] * qpow(d2, k) % MOD) % MOD;
if(d1 != d2) res = (res + 1ll * mu[d2] * qpow(d1, k) % MOD) % MOD;
if(res < 0) res += MOD;
}
}
pre[i] = (pre[i - 1] + res) % MOD;
}
}
map <int, ll> mp;
ll djs(int n) {
if(n < N) return pre[n];
if(mp.find(n) != mp.end()) return mp[n];
ll ans = lagrange.calc(n);
for(int i = 2, j; i <= n; i = j + 1) {
j = n / (n / i);
ans -= 1ll * (j - i + 1) * djs(n / i) % MOD;
if(ans < 0) ans += MOD;
}
return mp[n] = ans;
} void run(){
lagrange.init(k + 1);
init();
int ans = djs(n);
cout << ans << '\n';
} int main() {
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
cout << fixed << setprecision(20);
while(cin >> n >> k) run();
return 0;
}

EOJ Monthly 2019.11 E. 数学题(莫比乌斯反演+杜教筛+拉格朗日插值)的更多相关文章

  1. 洛谷P3768 简单的数学题 莫比乌斯反演+杜教筛

    题意简述 求出这个式子 \[ \sum_{i=1}^n\sum_{j=1}^n ij(i,j) \bmod p \] 做法 先用莫比乌斯反演拆一下式子 \[ \begin{split} \sum_{i ...

  2. 「洛谷P3768」简单的数学题 莫比乌斯反演+杜教筛

    题目链接 简单的数学题 题目描述 输入一个整数n和一个整数p,你需要求出 \[\sum_{i=1}^n\sum_{j=1}^n (i\cdot j\cdot gcd(i,j))\ mod\ p\]  ...

  3. LOJ#6229. 这是一道简单的数学题(莫比乌斯反演+杜教筛)

    题目链接 \(Description\) 求\[\sum_{i=1}^n\sum_{j=1}^i\frac{lcm(i,j)}{gcd(i,j)}\] 答案对\(10^9+7\)取模. \(n< ...

  4. luogu 3768 简单的数学题 (莫比乌斯反演+杜教筛)

    题目大意:略 洛谷传送门 杜教筛入门题? 以下都是常规套路的变形,不再过多解释 $\sum\limits_{i=1}^{N}\sum\limits_{j=1}^{N}ijgcd(i,j)$ $\sum ...

  5. [复习]莫比乌斯反演,杜教筛,min_25筛

    [复习]莫比乌斯反演,杜教筛,min_25筛 莫比乌斯反演 做题的时候的常用形式: \[\begin{aligned}g(n)&=\sum_{n|d}f(d)\\f(n)&=\sum_ ...

  6. 【bzoj3930】[CQOI2015]选数 莫比乌斯反演+杜教筛

    题目描述 我们知道,从区间[L,H](L和H为整数)中选取N个整数,总共有(H-L+1)^N种方案.小z很好奇这样选出的数的最大公约数的规律,他决定对每种方案选出的N个整数都求一次最大公约数,以便进一 ...

  7. [BZOJ 3930] [CQOI 2015]选数(莫比乌斯反演+杜教筛)

    [BZOJ 3930] [CQOI 2015]选数(莫比乌斯反演+杜教筛) 题面 我们知道,从区间\([L,R]\)(L和R为整数)中选取N个整数,总共有\((R-L+1)^N\)种方案.求最大公约数 ...

  8. 2019年南京网络赛E题K Sum(莫比乌斯反演+杜教筛+欧拉降幂)

    目录 题目链接 思路 代码 题目链接 传送门 思路 首先我们将原式化简: \[ \begin{aligned} &\sum\limits_{l_1=1}^{n}\sum\limits_{l_2 ...

  9. LOJ#6491. zrq 学反演(莫比乌斯反演 杜教筛)

    题意 题目链接 Sol 反演套路题? 不过最后一步还是挺妙的. 套路枚举\(d\),化简可以得到 \[\sum_{T = 1}^m (\frac{M}{T})^n \sum_{d \ | T} d \ ...

随机推荐

  1. Prometheus监控(二)

    Prometheus监控(二) 数据类型 Counter(计数器类型) Counter类型的指标的工作方式和计数器一样,只增不减(除非系统发生了重置),Counter一般用于累计值. Gauges(仪 ...

  2. swiper 轮播中常用的效果,持续更新

    swiper一款非常好用的轮播插件,支持移动端和PC端,用过很多次了,这次简单的总结一下.方便以后查找使用,说明一下,下面的例子是基于swiper 4.0+版本的,如果你是其他的版本,请自行前往官网查 ...

  3. Effect:Mobile ocd

    Satisfy the following two Keep your phone at all times Check your phone even if there's no news Alwa ...

  4. centos和Ubuntu系统最小化安装基础命令

    CentOS系统常用的基础软件如下 yum install vim iotop bc gcc gcc-c++ glibc glibc-devel pcre \ pcre-devel openssl o ...

  5. 【机器学习基础】交叉熵(cross entropy)损失函数是凸函数吗?

    之所以会有这个问题,是因为在学习 logistic regression 时,<统计机器学习>一书说它的负对数似然函数是凸函数,而 logistic regression 的负对数似然函数 ...

  6. poj 3061 Subsequence 二分 前缀和 双指针

    地址 http://poj.org/problem?id=3061 解法1 使用双指针 由于序列是连续正数 使用l r 表示选择的子序列的起始 每当和小于要求的时候 我们向右侧扩展 增大序列和 每当和 ...

  7. C++ std::vector emplace_back 优于 push_back 的理由

    #include <iostream> #include <vector> #include <chrono> #include <windows.h> ...

  8. Java之String类

    String类概述 java.lang.String 类代表字符串.Java程序中所有的字符串文字(例如 "abc" )都可以被看作是实现此类的实例.其实就是说:程序当中所有的双引 ...

  9. 几行代码轻松实现PHP文件打包下载zip

    <?php //获取文件列表 function list_dir($dir){ $result = array(); if (is_dir($dir)){ $file_dir = scandir ...

  10. typescript与nodejs(一)最简单的webserver

    安装nodejs tsc cnpm vscode 这些略 如果网络慢,可以考虑使用CNPM 一. 基本WebServer模块环境 1. 命令行  npm init 初始化一个目录为nodejs项目 2 ...