2020.9.15考试总结(2019安师大CSP模拟)

gugu

题意

给定 N ∗ M N*M NM的图,只能向下或向右走,有 Q Q Q个限制,必须从 ( a i , b i ) (a_i,b_i) (ai,bi)走到 ( c i , d i ) (c_i,d_i) (ci,di),求从 ( 1 , 1 ) (1,1) (1,1)走到 ( N , M ) (N,M) (N,M)的方案数。

解题

给每个 ( a i , b i ) (a_i,b_i) (ai,bi)赋移动方向, ( c i , d i ) (c_i,d_i) (ci,di)不在 ( a i + 1 , b i ) (a_i+1,b_i) (ai+1,bi) ( a i , b i + 1 ) (a_i,b_i+1) (ai,bi+1)的直接赋 − 1 -1 1 ( a i , b i ) (a_i,b_i) (ai,bi)有两个及以上限制的也赋 − 1 -1 1。然后直接 N ∗ M N*M NM的基础 D P DP DP推过去就行了:
f i , j = f i − 1 , j ∗ ( g i − 1 , j = = 1 ) + f i , j − 1 ∗ ( g i , j − 1 = = 2 ) f_{i,j}=f_{i-1,j}*(g_{i-1,j}==1)+f_{i,j-1}*(g_{i,j-1}==2) fi,j=fi1,j(gi1,j==1)+fi,j1(gi,j1==2)

代码

const int mo=1e9+7;
int n,m,t;
int mp[3010][3010];
int f[3010][3010];

int main()
{
	freopen("gugu.in","r",stdin);
	freopen("gugu.out","w",stdout);
	n=gi<int>(),m=gi<int>(),t=gi<int>();
	for(int i=1;i<=t;i++)
	{
		int a,b,c,d;
		a=gi<int>(),b=gi<int>(),c=gi<int>(),d=gi<int>();
		if(mp[a][b]!=0) mp[a][b]=-1;
		else if(a==c && d==b+1) mp[a][b]=1;
		else if(b==d && c==a+1) mp[a][b]=2;
		else mp[a][b]=-1;
	}
	f[1][0]=1;
	mp[1][0]=1;
	for(int i=1;i<=n;i++)
	for(int j=1;j<=m;j++)
	f[i][j]=(1LL*f[i-1][j]*(mp[i-1][j]==2 || mp[i-1][j]==0)+f[i][j-1]*(mp[i][j-1]==1 || mp[i][j-1]==0))%mo;
	pi(f[n][m]);
	return 0;
}

letter

题意

一串仅包含 A B C ABC ABC的字符 S S S,一个栈。

三种操作:1.入栈一个字母;2.打印栈顶字母;3.出栈栈顶元素。

求多少次操作可打印出 S S S,打印完需保证栈为空。

解题

枚举中点,中点之前打印字母进行三种操作:

1.栈顶就是要打印的字母,直接打印;

2.栈顶不是,但第二个元素是,出栈然后打印;

3.否则入栈然后打印;

中点之后只考虑出栈不入栈。

就这么简单,但考试的时候只想到了前后的操作,但觉得要不断这样变换操作,后来讨论发现只要枚举一个中点就好了~~,人都傻了~~。

代码

const int N=5010;
int a[N];
int n;

inline void get()
{
	char ch[N];
	scanf("%s",ch+1);
	n=strlen(ch+1);
	for(int i=1;i<=n;a[i]=ch[i]-'A'+1,i++);
}

int q[N];
int top=0;
int ans=1e9+10;
 
int main()
{
	freopen("letter.in","r",stdin);
	freopen("letter.out","w",stdout);
	get();
	for(int i=(n>>1);i<=n;i++)
	{
		int sum=0;
		top=0;
		for(int j=1;j<=i;j++)
		{
			if(top>=1 && q[top]==a[j]) sum++;
			else if(top>=2 && q[top-1]==a[j]) top--,sum+=2;
			else q[++top]=a[j],sum+=2;
		}
		for(int j=i+1;j<=n;j++)
		{
			while(top>0 && q[top]!=a[j]) top--,sum++;
			if(top==0) break;
			sum++;
		}
		if(top!=0) ans=min(ans,sum+top);
	}
	pi(ans);
	return 0;
}

math

题意

在这里插入图片描述

解题

f m i n = ( l − 1 ) ∗ ( l − 1 ) 4 − ( l − 1 ) ∗ ( l − 1 ) 2 + l ∗ l f 最 小 的 数 组 个 数 = C l − 1 2 − 1 n − l − 1 2 − 2 f_{min}=\frac{(l-1)*(l-1)}4-\frac{(l-1)*(l-1)}2+l*l \\ f最小的数组个数=C^{n-\frac{l-1}2-2}_{\frac{l-1}2-1} fmin=4(l1)(l1)2(l1)(l1)+llf=C2l11n2l12

代码

const int mo=1e9+7;
ll n,l,ans;
int flg;

ll qmul(ll a,int b){ll sum=1;while(b){if(b&1)
sum=sum*a%mo;a=a*a%mo,b>>=1;}return sum;}

ll C(ll n,ll m)
{
	ll s1=1,s2=1;
	for(int i=1;i<=m;i++) s1=s1*(n-i+1)%mo;
	for(int i=1;i<=m;i++) s2=s2*i%mo;
	return s1*qmul(s2,mo-2)%mo;
}

int main()
{
	freopen("math.in","r",stdin);
	freopen("math.out","w",stdout);
	gi(n),gi(l),gi(flg);
	ans=(l-1)>>1;
	pi(ans*ans-(l-1)*ans+l*l);
	if(flg)
	{
		ll mx=n-1-(ans<<1);
		pi(C(mx+ans-1,ans-1));
	}
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值