(联考)noip94

T1

考场想的是 \(dp_{i,j}\) 表示已经拿了 \(i\) 个瓜子, \(j\) 个瓜子壳的期望次数,然后发现不会转移,于是死了,后来发现最多拿 \(3n-2\) 次,于是想算出每种次数的方案数,然而不合法的不会搞,于是死了。

正解的dp跟一开始想的一样,然而不会推。

所以可以去推概率,然后最后拿次数一乘就是期望。

设 \(dp_{i,j}\) 表示当前拿了 \(i\) 个瓜子,用了 \(j\) 次的概率。

转移则枚举当前拿的是瓜子还是瓜子壳即可。

不过由 \((i-1,j-1),(i,j-1)\) 转移到 \((i,j)\) 一直错,可能是自己写假了,改成由 \((i,j)\) 转移到 \((i+1,j+1),(i,j+1)\) 就对了。

Code
#include<cstdio>
#include<cctype>
#define re register
const int MAX = 2e3+3;
#define int long long
#define scanf oma=scanf
const int mod = 998244353;
#define freopen file=freopen
int oma;
FILE* file;
namespace some
{
	struct stream
	{
		template<typename type>inline stream &operator >>(type &s)
		{
			bool w=0; s=0; char ch=getchar();
			while(!isdigit(ch)){ w|=ch=='-'; ch=getchar(); }
			while(isdigit(ch)){ s=(s<<1)+(s<<3)+(ch^48); ch=getchar(); }
			return s=w?-s:s,*this;
		}
	}cin;
	int n,m,inv[MAX*3];
	int dp[MAX][MAX*3],ans;
	auto quickpow = [](int a,int b,int res = 1)
	{
		while(b)
		{
			if(b&1)
			{ res = res*a%mod; }
			a = a*a%mod,b >>= 1;
		}
		return res;
	};
	#define debug(s) printf("%s\n",s)
}using namespace some;
namespace OMA
{
	auto main = []() -> signed
	{
		//#define local
		#ifdef local
		debug("look here! if you want submit,please closed this");
		freopen("node.in","r",stdin); freopen("my.out","w",stdout);
		#endif
		freopen("eat.in","r",stdin); freopen("eat.out","w",stdout);
		cin >> n; m = 3*n-2,inv[1] = 1;
		for(re int i=2; i<=m; i++)
		{ inv[i] = (mod-mod/i)*inv[mod%i]%mod; }
		dp[1][1] = 1;
		for(re int i=1; i<n; i++)
		{
			for(re int j=1; j<=3*i; j++)
			{
				(dp[i+1][j+1] += dp[i][j]*(n-i)%mod*inv[n+2*i-j]%mod) %= mod;
				(dp[i][j+1] += dp[i][j]*(3*i-j)%mod*inv[n+2*i-j]%mod) %= mod;
			}
		}
		for(re int i=n; i<=m; i++)
		{ (ans += dp[n][i]*i%mod) %= mod; /*printf("dp[n][%lld]=%lld\n",i,dp[n][i]);*/ }
		printf("%lld\n",ans);
		return 0;
	};
}
signed main()
{ return OMA::main(); }

T2

40pts:暴力主席树。

40+20pts: \(k=1\) 的部分分,直接单调栈即可。

100pts:

一个数要成为第 \(k\) 大,则要求这段区间内有 \(k-1\) 个比它大的数,拿个双向链表写就行。

Code
//#pragma GCC optimize(3)
#include<cstdio>
#include<cctype>
#define re register
const int MAX = 5e5+3;
#define long long long
#define scanf oma=scanf
#define freopen file=freopen
int oma;
FILE* file;
namespace some
{
	struct stream
	{
		template<typename type>inline stream &operator >>(type &s)
		{
			bool w=0; s=0; char ch=getchar();
			while(!isdigit(ch)){ w|=ch=='-'; ch=getchar(); }
			while(isdigit(ch)){ s=(s<<1)+(s<<3)+(ch^48); ch=getchar(); }
			return s=w?-s:s,*this;
		}
	}cin;
	long ans;
	int n,k,a[MAX],val[81][2];
	#define debug(s) printf("%s\n",s)
}using namespace some;
namespace Data_Structures
{
	struct node
	{ int pre,next,id; }list[MAX];
	#define id(p) list[p].id
	#define pre(p) list[p].pre
	#define next(p) list[p].next
}using namespace Data_Structures;
namespace OMA
{
	auto main = []() -> signed
	{
		//#define local
		#ifdef local
		debug("look here! if you want submit,please closed this");
		freopen("node.in","r",stdin); //freopen("my.out","w",stdout);
		#endif
		freopen("kth.out","w",stdout); freopen("kth.in","r",stdin);
		cin >> n >> k; id(a[0] = n+1) = 0,id(a[n+1] = n+2) = n+1;
		for(re int i=1; i<=n; i++)
		{ cin >> a[i];}
		for(re int i=1; i<=n; i++)
		{ list[a[i]] = (node){a[i-1],a[i+1],i}; }
		for(re int i=1,p1,p2; i<=n; i++)
		{
			p1 = p2 = -1;
			for(re int j=i; j&&p1<k; j=pre(j))
			{ val[++p1][0] = id(j); }
			for(re int j=i; j&&p2<k; j=next(j))
			{ val[++p2][1] = id(j); }
			for(re int j=1; j<=p1; j++)
			{
				if(k-j<p2)
				{ ans += 1ll*i*(val[j-1][0]-val[j][0])*(val[k-j+1][1]-val[k-j][1]); }
			}
			pre(next(i)) = pre(i),next(pre(i)) = next(i);
		}
		printf("%lld\n",ans);
		return 0;
	};
}
signed main()
{ return OMA::main(); }

T3

solution

(联考)noip94

T4

solution

(联考)noip94
(联考)noip94

上一篇:noip96


下一篇:Python进阶之re模块