您的位置:首页 > 其它

常州大学新生寒假训练会试 G 零下e度 【错排公式 + n!/e】

2018-02-15 21:25 381 查看

题目描述

在家好冷!

又多冷呢?

大概是零下e度!

为什么是零下e度呢?

不知道,因为我编不下去了。

求给定一个数n,求出最接近n!/e的整数

输入描述:

一行一个整数n

1<=n<=10^8

输出描述:

一行一个整数,即题目描述中所求,由于这个数字可能很大,我们只需要知道mod 998244353后的结果(出题人负责任地告诉你,这个数字是个质数)

示例1

输入

6

输出

265

示例2

输入

87

输出

158005593

示例3

输入

16777216

输出

16065816

题意: 略

分析: 通过这个题学到的东西不少,首先是普通的递推,
D(n) = (n - 1)*(D(n - 1) + D(n - 2));
,由于容斥的推导公式如下:

正整数1, 2, 3, ……, n的全排列有 n! 种,其中第k位是k的排列有 (n-1)! 种;当k分别取1, 2, 3, ……, n时,共有n*(n-1)!种排列是至少放对了一个的,由于所求的是错排的种数,所以应当减去这些排列;但是此时把同时有两个数不错排的排列多排除了一次,应补上;在补上时,把同时有三个数不错排的排列多补上了一次,应排除;……;继续这一过程,得到错排的排列种数为

D(n)=n!−n!/1!+n!/2!−n!/3!+…+(−1)n∗n!/n!=∑(k=2 n)(−1)k∗n!/k!,D(n)=n!−n!/1!+n!/2!−n!/3!+…+(−1)n∗n!/n!=∑(k=2 n)(−1)k∗n!/k!,

即D(n)=n![1/0!−1/1!+1/2!−1/3!+1/4!+...+(−1)n/n!].D(n)=n![1/0!−1/1!+1/2!−1/3!+1/4!+...+(−1)n/n!].由此可知
n!/e
就是
D(n)
,由于n的范围为 1e8,我们用三个变量模拟即可,当然也可以用矩阵快速幂快点,我就简单用了变量模拟了下

参考代码

#include <bits/stdc++.h>

using namespace std;
typedef long long ll;
const ll MOD = 998244353;

int main() {
int n;
scanf("%d",&n);
if(n == 1) {
puts("0");
} else if(n == 2) {
puts("1");
} else {
ll a = 0,b = 1,c;
for (int i = 3; i <= n; i++) {
c = ((i - 1) * 1ll * (a + b)) % MOD;
a = b;
b = c;
}
printf("%lld\n",c);
}

return 0;
}


如有错误或遗漏,请私聊下UP,thx
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: