AT_abc471_e
AtCoder - abc471_e
闲得蛋疼写片
题解
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=2e6+5;
const ll mod=998244353;
ll fac[maxn],ifac[maxn];
ll powmod(ll x,ll y) {
if (!y) return 1;
ll t=powmod(x,y/2);
if (y&1) return t*t%mod*x%mod;
else return t*t%mod;
}
ll C(ll n,ll m) {
if (m<0||n<0||n<m) return 0;
return fac[n]*ifac[m]%mod*ifac[n-m]%mod;
}
ll n,k;
void solve() {
cin>>n>>k;
ll s1=0,s2=0;
for (int i=1;i<=n;i++) {
ll x;cin>>x;
s1=(s1+x)%mod;
s2=(s2+x*x%mod)%mod;
}
ll ans=((s1*s1%mod*C(n-2,k-2)%mod-s2*C(n-2,k-2)%mod+mod)%mod+s2*C(n-1,k-1)%mod)%mod;
cout<<ans<<'\n';
}
void prework() {
fac[0]=1;
for (ll i=1;i<maxn;i++) fac[i]=fac[i-1]*i%mod;
ifac[maxn-1]=powmod(fac[maxn-1],mod-2);
for (ll i=maxn-2;i>=0;i--) ifac[i]=ifac[i+1]*(i+1)%mod;
}
int main() {
ios::sync_with_stdio(0);
prework();
int t=1;
while (t--) solve();
}
\[\displaystyle(\sum_{x\in{S}} x)^{2}\\
=(x_{1}+x_{2}+...+x_{k})·(x_{1}+x_{2}+...+x_{k})+...+(x_{n-k+1}+x_{n-k+2}+...+x_{n})·(x_{n-k+1}+x_{n-k+2}+...+x_{n})
\]
显然最终可以变成一个式子:(其中A,B是系数)
\[A \times \displaystyle\sum_{i=1}^{n} {x_{i}^{2}} + B \times \displaystyle\sum_{i,j\in[1,n],i\neq j}{x_ix_j}
\]
考虑每个数自己和自己相乘的次数
即在确定了一个数的情况下,在剩下的 \(n-1\) 个数中再选 \(k-1\) 个数的方案:\(A=C^{k-1}_{n-1}\)
考虑两个每个数互相乘的次数
即在确定了两个数的情况下,在剩下的 \(n-2\) 个数中再选 \(k-2\) 个数的方案:\(B=C^{k-2}_{n-2}\)
所以答案就是
\[C^{k-1}_{n-1} \times \displaystyle\sum_{i=1}^{n} {x_{i}^{2}} + C^{k-2}_{n-2} \times \displaystyle\sum_{i,j\in[1,n],i\neq j}{x_ix_j}\\
=C^{k-1}_{n-1} \times \displaystyle\sum_{i=1}^{n} {x_{i}^{2}}+C^{n-2}_{k-2}\times (\displaystyle\sum^{n}_{i=1}{x})^{2}-C^{n-2}_{k-2} \times \displaystyle\sum_{i=1}^{n} {x_{i}^{2}}
\]
根据初中数学知识转化一下式子就可以O(n) 做了

浙公网安备 33010602011771号