第13届景驰-埃森哲杯广东工业大学ACM程序设计大赛 H-哲哲的疑惑
链接:https://www.nowcoder.com/acm/contest/90/H
来源:牛客网
题目描述
哲哲有l个球,球是不同的,现在她要用n种颜色给它们染色,如果一种染色方案有k种颜色没有用到,那么哲哲会产生C(k,m)的不满意度。
现在哲哲想求所有方案的不满意度之和,然而她只知道1+1=9,而她的神犇朋友maple去FW战队当中单了不在她身边,所以并不会求,你能帮帮她吗?
输入描述:
三个数n,m,l
1<=n,m<=10^7,l<=10^18
输出描述:
一个数(对998244353取模),表示所有方案的不满意度之和
示例1
输入
3 2 2
输出
3
说明
有以下方案:
两个球同色,有2种颜色没有用到,哲哲产生C(2,2)=1的不满意度,然后这里有三种方案,共产生3的不满意度
两个球不同色,有1种颜色没有用到,哲哲很开心(*^▽^*)
所以总共产生3的不满意度
示例2
输入
1634 1542 130
输出
93812204
说明
无可奉告
思路
答案显然是下式(枚举 i, 表示我用了 i 种颜色):
(为了更好的阅读享受,以下内容使用LaTeX编写,由于第一次使用,折腾了好久)
回顾一下概率论与数理统计的知识:
全排列公式二项式系数::Ann=n!Crn=(nr)=n!r!(n−r)!(25)(26)
(25)
全
排
列
公
式
:
A
n
n
=
n
!
(26)
二
项
式
系
数
:
C
n
r
=
(
n
r
)
=
n
!
r
!
(
n
−
r
)
!
ans======∑i=0n(ni)∗(li)∗i!∗f(n−i)∑i=0n(ni)∗f(n−i)∗∑j=0i(ij)∗(−1)i−j∗jl∑j=0njl∗(−1)j∗∑i=jn(−1)i∗(ni)∗(ij)∗f(n−i)∑j=0njl∗(−1)j∗(nj)∗∑i=jn(−1)i∗(n−ji−j)∗f(n−i)∑j=0njl∗(nj)∗∑i=0n−j(−1)i∗(n−ji)∗f(n−j−i)∑j=0njl∗(nj)∗∑i=0n−j(−1)n−j−i∗(n−ji)∗f(i)(3)(4)(5)(6)(7)(8)
(3)
a
n
s
=
∑
i
=
0
n
(
n
i
)
∗
(
l
i
)
∗
i
!
∗
f
(
n
−
i
)
(4)
=
∑
i
=
0
n
(
n
i
)
∗
f
(
n
−
i
)
∗
∑
j
=
0
i
(
i
j
)
∗
(
−
1
)
i
−
j
∗
j
l
(5)
=
∑
j
=
0
n
j
l
∗
(
−
1
)
j
∗
∑
i
=
j
n
(
−
1
)
i
∗
(
n
i
)
∗
(
i
j
)
∗
f
(
n
−
i
)
(6)
=
∑
j
=
0
n
j
l
∗
(
−
1
)
j
∗
(
n
j
)
∗
∑
i
=
j
n
(
−
1
)
i
∗
(
n
−
j
i
−
j
)
∗
f
(
n
−
i
)
(7)
=
∑
j
=
0
n
j
l
∗
(
n
j
)
∗
∑
i
=
0
n
−
j
(
−
1
)
i
∗
(
n
−
j
i
)
∗
f
(
n
−
j
−
i
)
(8)
=
∑
j
=
0
n
j
l
∗
(
n
j
)
∗
∑
i
=
0
n
−
j
(
−
1
)
n
−
j
−
i
∗
(
n
−
j
i
)
∗
f
(
i
)
设:∵∴∵∴∴f(i)=cm∗(im)+cm−1∗(im−1)+…+c0∗(i0)∑i=0n−j(−1)n−j−i∗(n−ji)∗f(i)是把f(i)差分k次后的f(0)原式=∑j=0njl∗(nj)∗cn−j这里f(i)=(im)只有cm=1原式=(n−m)l∗(nm)(9)(10)(11)(12)(13)(14)
(9)
设
:
f
(
i
)
=
c
m
∗
(
i
m
)
+
c
m
−
1
∗
(
i
m
−
1
)
+
…
+
c
0
∗
(
i
0
)
(10)
∵
∑
i
=
0
n
−
j
(
−
1
)
n
−
j
−
i
∗
(
n
−
j
i
)
∗
f
(
i
)
是
把
f
(
i
)
差
分
k
次
后
的
f
(
0
)
(11)
∴
原
式
=
∑
j
=
0
n
j
l
∗
(
n
j
)
∗
c
n
−
j
(12)
∵
这
里
f
(
i
)
=
(
i
m
)
(13)
∴
只
有
c
m
=
1
(14)
∴
原
式
=
(
n
−
m
)
l
∗
(
n
m
)
AC代码
注:使用原始快速幂可以AC。使用优化后的快速幂由于循环会报运行超时,case通过率为90.91%。
#include <iostream>
#include <array>
typedef long long ll;
using namespace std;
const int Mod = 998244353;
const int N = 30000050;
array<int, N> ni;
// 优化后的快速乘
ll QuickMulti_opt(ll a, ll b, ll c) {
ll ret = 0;
while(b) {
if(b&1) {
ret += a;
if(ret >= c)
ret -= c;
}
a <<= 1;
if(a >= c)
a -= c;
b >>= 1;
}
return ret;
}
// 优化后的快速幂
ll QuickMod_opt(ll a, ll b, ll c) {
ll ret = 1;
while(b) {
if(b&1) {
ret = QuickMulti_opt(a,ret,c);
}
b >>= 1;
a = QuickMulti_opt(a,a,c);
}
return ret;
}
// 原始的快速幂
ll QuickMod(ll a,ll b,ll c) {
ll ans = 1;
while(b) {
if(b&1)
ans = ans*a%c;
b >>= 1;
a = a*a%c;
}
return ans;
}
int main() {
ll n,m,l;
cin >> n >> m >> l;
ll ans=1;
for(int i=n-m+1; i<=n; i++) {
ans=ans*i%Mod;
}
ni[1]=1;
for(int i=2; i<=m; i++) {
ni[i]=-1LL*(Mod/i)*ni[Mod%i]%Mod;
}
for (int i=1; i<=m; i++) {
ans=ans*ni[i]%Mod;
}
ans=ans*QuickMod_opt(n-m,l,Mod)%Mod;
cout << (ans+Mod)%Mod << endl;
return 0;
}