XTU 2022程设期中

吐槽一下用c++和cincout加速莫名其妙ce或re

黑子之光

累乘输出即可

#include <bits/stdc++.h>
#define ll __int64
using namespace std;
void solve()
{
	int n;
	ll sum=1;
	scanf("%d",&n);
	for (int i=1;i<=n;i++)
	{
		ll x;
		scanf("%d",&x);
		sum*=x;
	}
	printf("%I64d\n",sum);
}
int main()
{
//	ios::sync_with_stdio(0);
//    cin.tie(0);
//    cout.tie(0);
    
    int t;
    cin>>t;
	while (t--)
	{
		solve();
	}
	return 0;
}

一起摇摆

遍历每一行字符串,统计期中ji和zhiyin的数量,再用前缀和维护

#include <bits/stdc++.h>
#define ll long long
using namespace std;
int sum[10005];
void solve()
{
	int n,m;
	scanf("%d %d",&n,&m);
	for (int i=1;i<=n;i++)
	{
		string s;
		cin>>s;
		int len=s.length();
		for (int j=0;j<len;j++)
		{
			if (s[j]=='j')
			{
				if (s[j+1]=='i')
					sum[i]++,j+=1;
				continue;
			}
			if (s[j]=='z')
			{
				if (s[j+1]=='h'&&s[j+2]=='i'&&s[j+3]=='y'&&s[j+4]=='i'&&s[j+5]=='n')
					sum[i]++,j+=5;
				continue;
			}
		}
		sum[i]+=sum[i-1];
	}
	while (m--)
	{
		int l,r;
		cin>>l>>r;
		if (l>r)
			swap(l,r);
		printf("%d\n",sum[r]-sum[l-1]);
	}
}
int main()
{
//	ios::sync_with_stdio(0);
//    cin.tie(0);
//    cout.tie(0);
    
    solve();
	return 0;
}

ikun的problem

用s.find函数查找每句话(也可以手写函数判断),然后分类讨论各种情况

#include <bits/stdc++.h>
#define ll long long
using namespace std;
bool sym[15];
string pan[15];
string s;
void find(int i,int moshi)// 
{
	for (int j=1;j<pan[moshi].length();j++)
	{
		if (s[i+j]!=pan[moshi][j])
			return;
	}
	sym[moshi]=1;
}
void solve()
{
	memset(sym,0,sizeof(sym));
	string name;
	int t;
	cin>>name>>t;
	while (t--)
	{
		cin>>s;
		int len=s.length();
		for (int i=0;i<len;i++)
			if (s[i]>='A'&&s[i]<='Z')
				s[i]+=32;
		for (int i=0;i<len;i++)
		{
			for (int j=1;j<=8;j++)
			{
				if (s[i]==pan[j][0])
					find(i,j);
			}
		}
	}
	
	//讨论每种情况
	//先讨论是ikun还是小黑子 
	if (sym[2])
		cout<<"5\n";
	else
	{
		if (sym[1])
		{
			if (sym[3]&&sym[6])
				cout<<"4\n";
			else 
				cout<<"3\n";
		}
		else
		{
			int flag=1;
			for (int i=3;i<=8;i++)
			{
				if (i==4)
				{
					if (sym[i]||sym[i+1])
						i=6;
					else
						flag=0;
				}
				if (!sym[i])
					flag=0;
			}
			if (flag==0)
				cout<<"2\n";
			else 
				cout<<"1\n";
		}
	}
}
int main()
{
	ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    
    pan[1]="i_am_ikun";
    pan[2]="i_am_xiaoheizi";
    pan[3]="problem_describe";
    pan[4]="problem_source";
    pan[5]="problem_num";
    pan[6]="code_paste";
    pan[7]="solve";
    pan[8]="result";
    
    int t;
    cin>>t;
	while (t--)
	{
		solve();
	}
	return 0;
}

黑子的鸡脚

线性dp
dp[i][0]表示到第i个数,还没有用过小黑妹
dp[i][1]表示到第i个数,已经用过小黑妹
dp思路就是枚举到第i个数,然后查找i-k+1~i这个区间有sum个0(用前缀和预处理维护)
接下来进行状态转移:
sum==0 这个区间是满足题目条件的:
dp[i][0]=dp[i-k][0]+1;
dp[i][1]=dp[i-k][1]+1;
两种都能转移且答案+1

sum==1 这个区间可以使用小黑妹来满足条件:
dp[i][1]=dp[i-k][0]+1;

最后无论有多少0,可以让第i个数单独划分为一个区间,只需转移i-1的状态:
dp[i][0]=max(dp[i][0],dp[i-1][0]);
dp[i][1]=max(dp[i][1],dp[i-1][1]);

#include <bits/stdc++.h>
#define ll long long
using namespace std;
char ch[10005];
int dp[10005][2],sum[10005];
int main()
{
    int t;
   	scanf("%d",&t);
    while (t--)
    {
    	memset(dp,0,sizeof(dp));
    	int n,k;
    	scanf("%d %d",&n,&k);
    	getchar();
    	scanf("%s",ch+1);
    	for (int i=1;i<=n;i++)
    	{
    		sum[i]=sum[i-1];
    		if (ch[i]=='0')
    			sum[i]++;
		}
    	for(int i=k;i<=n;i++)
    	{
        	if (sum[i]-sum[i-k]==0)
        	{
            	dp[i][0]=dp[i-k][0]+1;
            	dp[i][1]=dp[i-k][1]+1;
        	}
        	if (sum[i]-sum[i-k]==1)
            	dp[i][1]=dp[i-k][0]+1;
       	 	dp[i][0]=max(dp[i][0],dp[i-1][0]);
        	dp[i][1]=max(dp[i][1],dp[i-1][1]);
    	}
    	printf("%d\n",max(dp[n][0],dp[n][1]));
    }
    return 0;
}

黑子的01串

找规律推结论,是一道构造题,但是题目要求字典序最大,所以还需要用到一点贪心的思想
首先考虑最简单的情况a=0或b=0
这种情况x只能为0

然后考虑x为1的情况 a=4 b=3
1111000这种情况只有在最中间的时候对答案又一个贡献
如果将末尾的0插入到两个1中间:
此时x=3 情况分别是1110100 1101100 1011100
要字典序最大则应为 1110100
类似的可以推出x=5 1101010
11 0101 0 中间两个01则贡献为22+1,依次可得n个01则贡献为2n+1

我们发现这是x为奇数的情况,那么接下思考x为偶数的情况
x=2 1110001
x=4 1101001
可以发现规律只需将x-1情况的第一个1移到最后一位即可


接下来思考-1的情况:
给出a,b求出x的范围
当ab都不为0 x最小为1
最大为(a+b-abs(a+b))

例如a=3,b=4
0101010 x最大为6
a=4,b=3
1010101 x最大为6

但是有一个特殊情况当a=b,x最大应该为a+b-1
所以由以上规律可以得到-1的情况


当a>=b
我们可以得出第一位一定是1
a<b
我们可以得出只有当x取最大的时候第一位才为0

根据以上规律,给出x为奇数时,只需构造出(x-1)/2个01,这个01串前面为剩余的1,后面为剩余的0
x为偶数时,只需将x-1构造出来的答案的第一位1移到最后一位
这种情况的特例:
a<b a=3,b=4时 x为最大值6时
如果按照这种构造方式:1010100 这是x=5的情况,将1移到最后一位并不是x=6的情况,所以特判一下,直接输出01串,最后输出剩余的0即可0101010

#include <bits/stdc++.h>
#define ll long long
using namespace std;
void solve()
{
	int a,b,x;
	scanf("%d %d %d",&a,&b,&x);
	int maxn;
	if (a==b)
		maxn=a+b-1;
	else
		maxn=a+b-abs(a-b);
	if (a==0||b==0)
	{
		if(x!=0)
			puts("-1");
		else
		{
			for (int i=1;i<=a;i++)
				printf("1");
			for (int i=1;i<=b;i++)
				printf("0");
			printf("\n");	
		}
		return;	
	}
	if (maxn<x||x<1)
	{
		puts("-1");
		return;
	}
	if (x%2==1)
	{
		for (int i=1;i<=a-(x-1)/2;i++)
			printf("1");
		for  (int i=1;i<=(x-1)/2;i++)
			printf("01");
		for (int i=1;i<=b-(x-1)/2;i++)
			printf("0");
	}
	else
	{
		if (x==a+b-abs(a-b)&&a<b)
		{
			for (int i=1;i<=x/2;i++)
				printf("01");
			for (int i=1;i<=b-x/2;i++)
				printf("0");
		}
		else
		{
			for (int i=1;i<=a-x/2;i++)
				printf("1");
			for (int i=1;i<=x/2-1;i++)
				printf("01");
			for (int i=1;i<=b-(x/2-1);i++)
				printf("0");
			printf("1");
		}
	}
	printf("\n");
}
int main()
{
    int t;
    scanf("%d",&t);
	while (t--)
	{
		solve();
	}
	return 0;
}


黑子的养鸡场

对于某一个鸡,他有ai个位置可以选,但是他会受到其它鸡(抢位置)的影响
将所有ai进行排序,优先让ai最小的选,那么第i个鸡就只剩下ai-i+1个位置可以选则(高中乘法原理)
然后每次乘都取余
a * b * c * d * e * f %mod = a * b%mod * c%mod * d%mod * e%mod

#include <bits/stdc++.h>
#define ll __int64
using namespace std;
const ll mod=998244353;
int a[105];
void solve()
{
	int n;
	ll sum=1;
	scanf("%d",&n);
	for (int i=1;i<=n;i++)
		scanf("%d",&a[i]);
//		cin>>a[i];
	sort(a+1,a+1+n);
	for (int i=1;i<=n;i++)
	{
		sum=(sum*(a[i]-i+1))%mod;
		if (sum==0)
			break;
	}
	printf("%I64d\n",sum);
//	cout<<sum<<"\n";
}
int main()
{
    int t;
    scanf("%d",&t);
	while (t--)
	{
		solve();
	}
	return 0;
}

黑子的展览柜

问题比较抽象,转化为一个走路问题,有一个n*n的方格,当在(x,y)位置时,只能向(x+1,y)或(x,y+1)走,并且无时无刻都应让x>=y

此时x代表大篮球的数量,y代表小篮球的数量

所以转化为了一个很经典的递推问题:
dp[i][j]=dp[i-1][j]+dp[i][j-1]
其中横坐标大于等于纵坐标

#include <bits/stdc++.h>
#define ll __int64
using namespace std;
ll dp[25][25];
void solve()
{
	int n;
	scanf("%d",&n);
	printf("%I64d\n",dp[n][n]);
	cout<<dp[n][n]<<"\n";
}
int main()
{
	dp[0][0]=1;
	for (int i=1;i<=20;i++)
	{
		dp[i][0]=1;
		for (int j=1;j<=i;j++)
		{
			if (i-1>=j)
				dp[i][j]+=dp[i-1][j];
			dp[i][j]+=dp[i][j-1];
		}
	}
    int t;
    scanf("%d",&t);
	while (t--)
	{
		solve();
	}
	return 0;
}

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值