传送门
谈点个人意见,不喜勿喷。
NOI2019里面第二失败的题,第一失败的是D1T1,但是是Idea最失败的题。
正解是纯粹的数学相关(简单来说就是实现上除了求逆元其他都可以用文化课知识来完成,而推导上更是和OI几乎毫无关联),而且部分分对正解几乎没有提示作用。
现在网上还有一大堆题解打着“猜结论也是做题的一种方式”的标语,而不去思考数学证明。诚然,猜结论确实是做题的一种方式,那你写NMD的题解啊,你自己做完完事算了,写题解只会浪费别人点进来的时间。
说实话,这道题,值得佩服的只有并没有猜结论直接列式子硬推出来的选手。
题解:
确实,有很多人猜到了结论,同步赛和现场都有人A掉这道题。
先说结论,按照该洗牌规则,若洗牌前的序列可以表示为一个 m m m 次多项式,则洗牌后的序列上各个位置的期望可以表示为一个不超过 m m m 次的多项式。
打一个表可以发现这个结论,虽然说打表几乎不会用在计数题里面,谁知道你模意义下到底对应什么组合数,但是这道题打表发现高阶差分为0即可注意到是多项式
设洗牌前的序列为 { f } \{f\} {f},洗牌后的序列为 { e } \{e\} {e},本次洗牌参数为 A A A。
考虑一一对应的贡献:
e i = 1 n i ‾ ( ∑ j = 1 A ( i − 1 j − 1 ) A j ‾ ( n − A ) i − j ‾ f j + ∑ j = 1 n − A ( i − 1 j − 1 ) A i − j ‾ ( n − A ) j ‾ f A + j ) e_i=\frac{1}{n^{\underline i}}\left(\sum_{j=1}^A{i-1\choose j-1}A^{\underline j}(n-A)^{\underline{i-j}}f_j+\sum_{j=1}^{n-A}{i-1\choose j-1}A^{\underline{i-j}}(n-A)^{\underline j}f_{A+j}\right) ei=ni1(j=1∑A(j−1i−1)Aj(n−A)i−jfj+j=1∑n−A(j−1i−1)Ai−j(n−A)jfA+j)
两部分长得非常像,考虑证明第一部分是关于 i i i 的不超过 m m m 次多项式。
将 ( i k ) {i\choose k} (ki) 看作关于 i i i 的多项式,任何关于 i i i 的多项式可以由 k ∈ Z k\in \mathbb Z k∈Z 的 ( i k ) {i\choose k} (ki) 线性组合得出。
于是我们只考虑最高项即可,注意到式子里面有 j − 1 j-1 j−1 在组合数里面,考虑用 ( j − 1 k ) {j-1\choose k} (kj−1) 来代替 f j f_j fj。
接下来的化简需要用到两个组合恒等式,组合意义都很明显就不赘述了,直接列出来:
( a b ) ( c a ) = ( c b ) ( c − b a − b ) {a\choose b}{c\choose a}={c\choose b}{c-b\choose a-b} (ba)(ac)=(bc)(a−bc−b)
∑ i ( n i ) ( m k − i ) = ( n + m k ) \sum_{i}{n\choose i}{m\choose k-i}={n+m\choose k} i∑(in)(k−im)=(kn+m)
对第一部分化简:
∑ j = 1 A 1 n i ‾ ( i − 1 j − 1 ) A j ‾ ( n − A ) i − j ‾ ( j − 1 k ) = ∑ j = 1 A ( j − 1 k ) ( i − 1 j − 1 ) A ! ( A − j ) ! ( n − A ) ! ( n − A − i + j ) ! ( n − i ) ! n ! = 1 ( n A ) ∑ j = 1 A ( i − 1 k ) ( i − 1 − k j − 1 − k ) ( n − i A − j ) = 1 ( n A ) ( i − 1 k ) ( n − k − 1 A − k − 1 ) \begin{aligned} &\sum_{j=1}^A\frac{1}{n^{\underline i}}{i-1\choose j-1}A^{\underline j}(n-A)^{\underline {i-j}}{j-1\choose k}\\ =&\sum_{j=1}^A{j-1\choose k}{i-1\choose j-1}\frac{A!}{(A-j)!}\frac{(n-A)!}{(n-A-i+j)!}\frac{(n-i)!}{n!}\\ =&\frac{1}{n\choose A}\sum_{j=1}^A{i-1\choose k}{i-1-k\choose j-1-k}{n-i\choose A-j}\\ =&\frac{1}{n\choose A}{i-1\choose k}{n-k-1\choose A-k-1} \end{aligned} ===j=1∑Ani1(j−1i−1)Aj(n−A)i−j(kj−1)j=1∑A(kj−1)(j−1i−1)(A−j)!A!(n−A−i+j)!(n−A)!n!(n−i)!(An)1j=1∑A(ki−1)(j−1−ki−1−k)(A−jn−i)(An)1(ki−1)(A−k−1n−k−1)
容易发现关于 i i i 的多项式只有 ( i − 1 k ) {i-1\choose k} (ki−1),是 k k k 次。
知道这个结论之后每次算出前三项的期望然后暴力解方程算系数即可。
代码:
#include<bits/stdc++.h>
#define ll long long
#define re register
#define cs const
namespace IO{
inline char gc(){
static cs int Rlen=1<<22|1;static char buf[Rlen],*p1,*p2;
return (p1==p2)&&(p2=(p1=buf)+fread(buf,1,Rlen,stdin),p1==p2)?EOF:*p1++;
}template<typename T>T get_integer(){
char c;bool f=false;while(!isdigit(c=gc()))f=c=='-';T x=c^48;
while(isdigit(c=gc()))x=((x+(x<<2))<<1)+(c^48);return f?-x:x;
}inline int gi(){return get_integer<int>();}
}using namespace IO;
using std::cerr;
using std::cout;
cs int mod=998244353,inv2=(mod+1)>>1;
inline int add(int a,int b){return a+b>=mod?a+b-mod:a+b;}
inline int dec(int a,int b){return a-b<0?a-b+mod:a-b;}
inline int mul(int a,int b){ll r=(ll)a*b;return r>=mod?r%mod:r;}
inline void Inc(int &a,int b){a+=b-mod;a+=a>>31&mod;}
inline void Dec(int &a,int b){a-=b;a+=a>>31&mod;}
inline void Mul(int &a,int b){a=mul(a,b);}
inline void ex_gcd(int a,int b,int &x,int &y){
if(!b){x=1,y=0;return;}ex_gcd(b,a%b,y,x);y-=a/b*x;
}inline int inv(int a){int x,y;ex_gcd(mod,a,y,x);return x+(x>>31&mod);}
template<class... Args>inline int add(int a,Args ...argc){return add(a,add(argc...));}
template<class... Args>inline int mul(int a,Args ...argc){return mul(a,mul(argc...));}
int n,m;
int invn_0,invn_1,invn_2,A,B,C;
inline int f(int x){return add(C,mul(x,add(B,mul(x,A))));}
void Main(){
n=gi(),m=gi();
invn_0=inv(n);
invn_1=inv(mul(n,n-1));
invn_2=inv(mul(n,n-1,n-2));
if(gi()==1)B=1;else A=1;
while(m--){
int x=gi(),p1=f(1),p2=f(2),p3=f(3);
int q1=f(x+1),q2=f(x+2),q3=f(x+3);
int v1=mul(invn_0,add(mul(x,p1),mul(n-x,q1)));
int v2=mul(invn_1,add(
mul(x,add(mul(x-1,p2),mul(n-x,q1))),
mul(n-x,add(mul(x,p1),mul(n-x-1,q2)))));
int v3=mul(invn_2,add(
mul(x,add(mul(x-1,add(mul(x-2,p3),mul(n-x,q1))),
mul(n-x,add(mul(x-1,p2),mul(n-x-1,q2))))),
mul(n-x,add(mul(x,add(mul(x-1,p2),mul(n-x-1,q2))),
mul(n-x-1,add(mul(x,p1),mul(n-x-2,q3)))))
));
A=dec(mul(inv2,add(v1,v3)),v2);
B=mul(inv2,add(mul(mod-5,v1),mul(8,v2),mul(mod-3,v3)));
C=add(mul(3,dec(v1,v2)),v3);
}m=gi();while(m--){cout<<f(gi())<<"\n";}
}
inline void file(){
#ifdef zxyoi
freopen("landlords.in","r",stdin);
#else
freopen("landlords.in","r",stdin);
freopen("landlords.out","w",stdout);
#endif
}signed main(){file();Main();return 0;}