noip模拟25

期望得分0+0+40=40
实际得分0+0+20=20
T1 看了眼题面,觉得不可做,就跳了。。。主要是因为看到了奇怪的题目描述之后瞬间就不好了。
其实什么随机选还有什么求逆序对个数可以归纳一下,,,随机选择序列可以按照长度划分,对于长度相同的序列,由于每个数两两不同,所以大小关系是相同的,离散化后当成一种情况就好了。这样的话,设f[i]为长度为i的序列的逆序对个数,考虑一个逆序对

\[f[n]=1+\frac{\sum^{n}_{i=0}{C^{n-i}_{n-2}*f[i]}}{2^n} \]

\[ans=\frac{\sum^{n}_{i=0}{C^{2}_{i}*\frac{1}{2}*f[i]}}{n} \]

除以2是因为选的两个数成为逆序和不成为逆序概率相等
打个表发现对于所有i>=2,f[i]是\(\frac{4}{3}\)。
用归纳法

\[f[n]=1+\frac{2^{n-2}*\frac{4}{3}}{2^n} \]

\[f[n]=\frac{4}{3} \]

然后化简式子

\[ans=\frac{\sum^{n}_{i=0}{C^{2}_{i}*\frac{1}{2}*f[i]}}{n} \]

\[\sum^{n}_{i=0}C^2_i=C^{3}_{n+1} \]

\[ans=\frac{n^2-1}{9} \]

T2 ,,,,,

T3,,
所有的合法图形只有六种,横着,竖着,斜着,还有九宫格里和四个角和中间的格,剩余的四个格和中间的格,正方形的四个角,分别求就行了,不会做图片,意会吧

T1

#include<bits/stdc++.h>
using namespace std;
const int mod=998244353;
#define int long long
inline int read()
{
	int s=0;
	char ch=getchar();
	while(ch>'9'||ch<'0')
		ch=getchar();
	while(ch>='0'&&ch<='9')
	{
		s=(s<<1)+(s<<3)+(ch^48);
		ch=getchar();
	}
	return s;
}
int fma(int x,int y)
{
	int ans=1;
	while(y)
	{
		if(y&1)
			ans=ans*x%mod;
		x=x*x%mod;
		y>>=1;
	}
	return ans;
}
signed main()
{
	long long n,t;
	t=read();
	while(t--)
	{
		n=read();
		printf("%lld\n",((n+1)%mod*(2*n%mod+1)%mod*fma(18,mod-2)%mod-(1+n)%mod*fma(6,mod-2)%mod+mod)%mod);
	}
	return 0;
}

T3

#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=4e5+11;
const int mod=3e5+7;
int n,m,k;
int jc[N],ny[N];
int qzh[N],qzh2[N];
inline int read()
{
	int s=0;
	char ch=getchar();
	while(ch>'9'||ch<'0')
		ch=getchar();
	while(ch>='0'&&ch<='9')
	{
		s=(s<<1)+(s<<3)+(ch^48);
		ch=getchar();
	}
	return s;	
}
int fma(int x,int y)
{
	int ans=1;
	while(y)
	{
		if(y&1)
			ans=ans*x%mod;
		x=x*x%mod;
		y>>=1;
	}
	return ans;
}
void pre()
{
	jc[0]=1;
	ny[0]=1;
	for(int i=1;i<N;i++)
	{
		jc[i]=jc[i-1]*i%mod;
		ny[i]=fma(jc[i],mod-2);
	}
	for(int i=1;i<N;i++)
	{
		qzh[i]=(qzh[i-1]+i)%mod;
		qzh2[i]=(qzh2[i-1]+qzh[i])%mod;
	}
	return;
}
int C(int a,int b)
{
	if(a>b)
		return 0;
	return jc[b]*ny[a]%mod*ny[b-a]%mod;
}
int lucas(int a,int b)
{
	if(!a)
		return 1;
	return C(a%mod,b%mod)*lucas(a/mod,b/mod)%mod;
}
signed main()
{
	int t=read();
	pre();
	while(t--)
	{
		n=read();
		m=read();
		k=read();
		if(k>m&&k>n)
		{
			printf("%d\n",0);
			continue;
		}
		if(k>5)
		{
			if(k>m&&k<=n)
			{
				printf("%lld\n",m%mod*lucas(k,n)%mod);
				continue;
			}
			if(k>n&&k<=m)
			{
				printf("%lld\n",n%mod*lucas(k,m)%mod);
				continue;
			}
			int minn=min(n,m);
			int maxx=max(n,m);
			int ans=(n%mod*lucas(k,m)%mod+m%mod*lucas(k,n)%mod)%mod;
			ans=(ans+4*lucas(k+1,minn))%mod;
			ans=(ans+2*(maxx-minn+1)%mod*lucas(k,minn)%mod)%mod;
			printf("%lld\n",ans);
		}
		else
		{
			if(k==1)
				printf("%lld\n",n%mod*(m%mod)%mod);
			if(k==2)
			{
				int ans=0;
				ans+=(n%mod*lucas(k,m)%mod+m%mod*lucas(k,n)%mod)%mod;
				int minn=min(m,n);
				int maxx=max(m,n);
				ans=(ans+4*lucas(k+1,minn))%mod;
				ans=(ans+2*(maxx-minn+1)%mod*lucas(k,minn)%mod)%mod;
				printf("%lld\n",ans);
			}
			if(k==3)
			{
				int ans2=0;
				int ans=0;
				if(k<=m)
					ans+=n%mod*lucas(k,m)%mod;
				if(k<=n)
					ans=(ans+m%mod*lucas(k,n)%mod)%mod;
				int minn=min(m,n);
				int maxx=max(m,n);
				if(minn>=3)
				{
					ans=(ans+8*lucas(3,minn)%mod)%mod;
					ans=(ans+4*(maxx-minn+1)%mod*lucas(2,minn)%mod)%mod;
					int ed1=min((m+1)/2,n)%mod;
					int ed2=min((n+1)/2,m)%mod;
					m%=mod;
					n%=mod;
					ans=(ans+2*n*m%mod*(ed1-1)%mod+2*(ed1-1)*ed1%mod*(2*ed1-1)%mod*fma(3,mod-2)%mod-ed1*(ed1-1)%mod*(2*n+m)%mod+mod)%mod;
					ans=(ans+2*n*m%mod*(ed2-1)%mod+2*(ed2-1)*ed2%mod*(2*ed2-1)%mod*fma(3,mod-2)%mod-ed2*(ed2-1)%mod*(2*m+n)%mod+mod)%mod;
				}
				if(minn>=2)
				{
					ans=(ans+4*lucas(4,minn)%mod)%mod;
					ans=(ans+2*((maxx-minn+1)%mod)%mod*lucas(3,minn)%mod)%mod;
				}
				printf("%lld\n",ans);
			}
			if(k==4)
			{
				int ans=0;
				if(k<=m)
					ans+=n%mod*lucas(4,m)%mod;
				if(k<=n)
					ans+=m%mod*lucas(4,n)%mod;
				int minn=min(n,m);
				int maxx=max(n,m);
				if(minn>=4)
				{
					ans=(ans+4*lucas(5,minn))%mod;
					ans=(ans+2*(maxx-minn+1)%mod*lucas(4,minn))%mod;
				}
				if(n>=2&&m>=3)
				{
					int ed=min((m+1)/2,n)%mod;
					ans=(ans+2*n%mod*(m%mod)%mod*(ed-1)%mod+2*(ed-1)*ed%mod*(2*ed-1)%mod*fma(3,mod-2)-ed*(ed-1)%mod*((2*n+m)%mod)%mod+mod)%mod;
				}
				if(n>=3&&m>=2)
				{
					int ed=min((n+1)/2,m)%mod;
					ans=(ans+2*n%mod*(m%mod)%mod*(ed-1)%mod+2*(ed-1)*ed%mod*(2*ed-1)%mod*fma(3,mod-2)-ed*(ed-1)%mod*((2*m+n)%mod)%mod+mod)%mod;
				}
				int ed=minn%mod;
				n%=mod;
				m%=mod;
				ans=(ans+n*m%mod*(ed-1)%mod+(ed-1)*ed%mod*(2*ed-1)%mod*fma(6,mod-2)-ed*(ed-1)%mod*(m+n)%mod*fma(2,mod-2)%mod+mod)%mod;
				ed=(minn-1)/2%mod;
				ans=(ans+5*(n*m%mod*ed%mod-(m+n)*2*(ed+1)%mod*ed%mod*fma(2,mod-2)%mod+4*(ed+1)*ed%mod*(2*ed+1)%mod*fma(6,mod-2)))%mod;
				printf("%lld\n",ans);
			}
			if(k==5)
			{
				int ans=0;
				if(k<=m)
					ans+=n%mod*lucas(5,m)%mod;
				if(k<=n)
					ans=(ans+m%mod*lucas(5,n)%mod)%mod;
				int minn=min(n,m);
				int maxx=max(n,m);
				if(minn>=5)
				{
					ans=(ans+4*lucas(6,minn)%mod)%mod;
					ans=(ans+2*(maxx-minn+1)%mod*lucas(5,minn)%mod)%mod;
				}
				int ed=(minn-1)/2%mod;
				m%=mod;
				n%=mod;
				ans=(ans+2*(n*m%mod*ed-(m+n)*2*(ed+1)%mod*ed%mod*fma(2,mod-2)%mod+4*(ed+1)*ed%mod*(2*ed+1)%mod*fma(6,mod-2)%mod))%mod;
				printf("%lld\n",ans);
			}
		}
	}
	return 0;
}

上一篇:2021牛客多校4 C - LCS (构造)


下一篇:题解 P1311 【选择客栈】