8.6
作者:互联网
CF1716F
题意:
有\(n\)个不同的包,每个包里有编号为\(1\sim m\)的球恰好一个。
从每个包里取一个球出来,假设某个取球方案中,奇数编号的球恰好有\(x\)个,则该方案的贡献是\(x^k\)。
求所有取球方案的贡献和。模\(998244353\)
\(1\leq T\leq 5000\)
\(1\leq n,m\leq 998244352,1\leq k\leq 2000\)
题解:
算贡献
设奇数编号球有\(i\)个,\(x=\lceil\frac{m}{2}\rceil,y=m-x\),\(x\)是奇数编号的球的总数,\(y\)是偶数编号的球的总数
\[ans=\sum_{i=1}^ni^k\dbinom{n}{i}x^iy^{n-i} \]现在考虑把关于\(i\)的求和变成关于\(k\)的求和
套用第二类斯特林数转化法
\[i^k=\sum_{j=0}^i\ \begin{Bmatrix}k \\ j\end{Bmatrix}*j!*\dbinom{i}{j} \]解释:组合意义来看,第二类斯特林数\(\begin{Bmatrix}n \\ m\end{Bmatrix}\)是\(n\)个有编号的球放入\(m\)个无标号的盒子,没有空盒子的方案数。
那么\(i^k\)的组合意义是把\(k\)个有编号的球放入\(i\)个有编号的盒子,有空盒子的方案数。(每个球都有\(i\)种选择方案)
根据这个意义,我们枚举有多少个盒子非空,即\(j=0->k\)
然后从\(i\)个盒子中选出\(j\)个,并且标号,即\(j!*\dbinom{i}{j}\)
最后再把这些球放进去\(\begin{Bmatrix}k \\ j\end{Bmatrix}\)
为什么是\(j!\)不是\(k!\),因为空盒是不用标号的,空盒里面的内容都一样,非空盒哪怕里面球的数量一样,球的编号也不一样。
关于第二类斯特林数的递推:
\[\begin{Bmatrix}n \\ m\end{Bmatrix}=\begin{Bmatrix}n-1 \\ m-1\end{Bmatrix}+m\begin{Bmatrix}n-1 \\ m\end{Bmatrix} \]解释:考虑最后一个球放在哪,要么自己新开一个盒子,要么放在原有的\(m\)个盒子其中的一个。
把转化后的式子代回去
\[ans=\sum_{i=1}^n\sum_{j=0}^i\ \begin{Bmatrix}k \\ j\end{Bmatrix}*j!*\dbinom{i}{j}*\dbinom{n}{i}*x^i*y^{n-i}\\ =\sum_{i=1}^n\sum_{j=0}^i\ \begin{Bmatrix}k \\ j\end{Bmatrix}*j!*\dbinom{n-j}{i-j}*\dbinom{n}{j}*x^i*y^{n-i}\\ \]解释下这里的变换:
\(\dbinom{i}{j}*\dbinom{n}{i}\)可以理解为,先从\(n\)个里面选\(i\)个二等奖,再从\(i\)个里面选\(j\)个一等奖
\(\dbinom{n-j}{i-j}*\dbinom{n}{j}\)可以变化为,直接从\(n\)个里面选\(j\)个一等奖,再从剩下的人里面选\(i-j\)个二等奖
\[ans=\sum_{j=0}^k\begin{Bmatrix}k \\ j\end{Bmatrix}*j!*\dbinom{n}{j}\sum_{i=j}^n\dbinom{n-j}{i-j}x^iy^{n-i} \]切换下标,设\(i'=i-j,i=i'+j\)
\[ans=\sum_{j=0}^k\begin{Bmatrix}k \\ j\end{Bmatrix}*j!*\dbinom{n}{j}\sum_{i'=0}^{n-j}\dbinom{n-j}{i'}x^{i'+j}y^{n-j-i'}\\ =\sum_{j=0}^k\begin{Bmatrix}k \\ j\end{Bmatrix}*j!*\dbinom{n}{j}*(x+y)^{n-j}*x^j \]就做完了,那个组合数虽然\(n\)很大,但是可以递推。
#include<bits/stdc++.h>
using namespace std;
namespace red{
#define int long long
#define double long double
#define ls(p) (p<<1)
#define rs(p) (p<<1|1)
#define lowbit(i) ((i)&(-i))
#define mid ((l+r)>>1)
#define eps (1e-15)
const int N=3e5+10,mod=998244353,inv2=5e8+4,inf=2e9;
vector S2(2001,vector<int>(2001));
vector<int> fac(2001);
void _init_(int n=2000)
{
S2[0][0]=1;
for(int i=0;i<=n;++i)
{
for(int j=1;j<=i;++j)
{
S2[i][j]=(S2[i-1][j-1]+j*S2[i-1][j])%mod;
}
}
fac[0]=1;
for(int i=1;i<=n;++i) fac[i]=fac[i-1]*i%mod;
}
inline void main()
{
int n,m,k;cin>>n>>m>>k;
int ans=0;
auto fast=[&](int x,int k) -> int
{
int ret=1;
while(k)
{
if(k&1) ret=ret*x%mod;
x=x*x%mod;
k>>=1;
}
return ret;
};
int x=(m+1)/2,y=m-x,cc=1;
int lim=min(n,k);
for(int i=0;i<=lim;++i)
{
ans=(ans+S2[k][i]*fac[i]%mod*cc%mod*fast(x+y,n-i)%mod*fast(x,i)%mod)%mod;
//cout<<n<<' '<<i<<' '<<cc<<"!!!"<<endl;
cc=cc*(n-i)%mod*fast(i+1,mod-2)%mod;
}
cout<<ans<<'\n';
}
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
red::_init_();
int qwq=1; cin>>qwq;
while(qwq--) red::main();
return 0;
}
/*
*/
CF1083E
题意:
给定 \(n\) 个平面直角坐标系中左下角为坐标原点,右上角为 \((x_i, y_i)\) 的矩形,每一个矩形拥有权值 \(a_i\),且保证任意两个矩形的面积不会出现包含关系。你的任务是选出若干个矩形,使得选出的矩形的面积并减去矩形的权值之和尽可能大。输出最大值。
\(1 \leq n \leq 10^6, 1 \leq x_i, y_i \leq 10^9, 0 \leq a_i \leq x_i \cdot y_i\),给出的矩形保证任意两个矩形的面积不会出现包含关系。
题解:
把矩形按右上角的\(x\)坐标排序,然后直接列方程
\[dp[i]=dp[j]+(x_i-x_j)*y_i-a_i\\ dp[j]=y_i*x_j+dp[i]-x_iy_i+a_i\\ y(j)=dp[j],x(j)=y_j,k=y_i \]就可以斜率优化了,因为斜率\(k_i\)是递减的,所以维护一个左上突壳
#include<bits/stdc++.h>
using namespace std;
namespace red{
#define int long long
#define double long double
#define ls(p) (p<<1)
#define rs(p) (p<<1|1)
#define lowbit(i) ((i)&(-i))
#define mid ((l+r)>>1)
#define eps (1e-15)
const int N=3e5+10,mod=998244353,inv2=5e8+4,inf=2e9;
void _init_(int n=2000) {}
struct node {double x,y,z;};
inline void main()
{
int n;
cin>>n;
vector<node> a(n+1);
for(int i=1;i<=n;++i)
{
int x,y,z;cin>>x>>y>>z;
a[i].x=x,a[i].y=y,a[i].z=z;
//cin>>a[i].x>>a[i].y>>a[i].z;
}
sort(a.begin()+1,a.end(),[](node &i,node &j){return i.x<j.x;});
vector<int> dp(n+2),q(n+2);
int head=0,tail=0;
auto y=[&](int &i) -> double{return dp[i];};
auto x=[&](int &i) -> double{return a[i].x;};
auto slope=[&](int &i,int &j) -> double
{
return 1.0*(y(i)-y(j))/(x(i)-x(j));
};
int ans=0;
for(int i=1;i<=n;++i)
{
while(head<tail&&slope(q[head],q[head+1])>=1.0*a[i].y) ++head;
int j=q[head];
dp[i]=dp[j]+(a[i].x-a[j].x)*a[i].y-a[i].z;
ans=max(ans,dp[i]);
while(head<tail&&slope(q[tail],q[tail-1])<=slope(q[tail-1],i)) --tail;
q[++tail]=i;
}
cout<<ans<<'\n';
}
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
red::_init_();
int qwq=1; //cin>>qwq;
while(qwq--) red::main();
return 0;
}
/*
*/
标签:begin,end,dbinom,8.6,int,leq,Bmatrix 来源: https://www.cnblogs.com/knife-rose/p/16559939.html