Educational Codeforces Round 170 (Rated for Div 2)解题记录


Two Screens

签到题
code:

#include <bits/stdc++.h>
using namespace std;
int T;
string s1,s2;
int len1,len2;
int main()
{
	ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
	cin >> T;
	while(T--)
	{
		cin >> s1;
		cin >> s2;
		len1 = s1.length();
		len2 = s2.length();
		if(len1 > len2)
		{
			swap(s1,s2);
			swap(len1,len2);
		}
		int cnt = 0,flag = 1;
		for(int i = 0;i < len1;i++)
		{
			if(s1[i] == s2[i] && flag == 1)
			{
				cnt ++;
			}
			else
			{
				flag = 0;
				break;
			}
		}
		cout << min(len1 + (len2 - cnt) + 1,len1 + len2) << endl; 
	}
	return 0;
}

### Binomial Coefficients, Kind Of

性质题,手玩一下不难发现\(C[n][k] = 2^k\)
code:

#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 1e5 + 10;
const int MOD = 1e9 + 7;
int T;
struct edge
{
	int n;
	int m;
}e[N];
int qpow(int t)
{
	int ret = 1;
	int g = 2;
	while(t)
	{
		if(t % 2 == 1)
			ret *= g,ret %= MOD;
		t /= 2;
		g *= g;
		g %= MOD;
	}
	return ret % MOD;
}
signed main()
{
	ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
	cin >> T;
	for(int i = 1;i <= T;i++)
		cin >> e[i].n;
	for(int i = 1;i <= T;i++)
		cin >> e[i].m;
	for(int i = 1;i <= T;i++)
	{
		cout << qpow(e[i].m) << endl;
	}
	return 0;
}

New Game

模拟题,暴力模拟找最大值即可

#include <bits/stdc++.h>
using namespace std;
const int N = 200000 + 10;
int T;
int n,k;
int f[N];
queue <int> q;
int main()
{
	ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
	cin >> T;
	while(T--)
	{
		cin >> n >> k;
		for(int i = 1;i <= n;i++)
			cin >> f[i];
		sort(f + 1,f + n + 1);
		int ans = 1;
		int sum = 0,tsum = 0,nowk = 1;
		f[0] = f[1];
		for(int i = 1;i <= n;i++)
		{
			if(f[i] == f[i - 1])
			{
				tsum ++;
				sum ++;
			}
			else if(f[i] == f[i - 1] + 1)
			{
				if(nowk < k)
				{
					q.push(tsum);
					tsum = 1;
					nowk++;
					sum++;
				}
				else
				{
					q.push(tsum);
					int u = q.front();
					ans = max(ans,sum);
					q.pop();
					sum -= u;
					sum++;
					tsum = 1;
				}
			}
			else 
			{

					ans = max(ans,sum);
					while(!q.empty())q.pop();
					sum = 1;
					tsum = 1;
					nowk = 1;
			}
		}
		ans = max(ans,sum);
		cout << ans << endl;
		while(!q.empty())q.pop();
	}
	return 0;
}

Attribute Checks

dp题,设\(dp[i][j]\)为对于第i个可以加分的机会时,j分加给了力量,此时可以通过的最多测试数,每个\(dp[i][j]\)均可由\(dp[i - 1][j - 1],dp[i-1][j]\) 转移而来,再用一个树状数组维护一下两个加分机会之间的测试需要分数即可,(智力与力量分别排序也是可以做的)。注意:一定要注意树状数组的最大范围

#include <bits/stdc++.h>
using namespace std;
const int N = 2e6 + 10;
int n,m;
int f[N];
int dp[5010][5010];
int tre1[5010];
int lowbit(int x)
{
	return x & (-x);
}
int query1(int x)
{
	int ret = 0;
	for(int i = x;i;i -= lowbit(i))
		ret += tre1[i];
	return ret;
}
void update1(int pos,int val)
{
	for(int i = pos;i <= m;i += lowbit(i))
		tre1[i] += val;
}
int tre2[5010];
int query2(int x)
{
	int ret = 0;
	for(int i = x;i;i -= lowbit(i))
		ret += tre2[i];
	return ret;
}
void update2(int pos,int val)
{
	for(int i = pos;i <= m;i += lowbit(i))
		tre2[i] += val;
}
int ans = 0;
int main()
{
	ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
	cin >> n >> m;
	for(int i = 1;i <= n;i++)
		cin >> f[i]; 
	int cnt = 0;
	for(int i = 1;i <= n;i++)
	{
		if(f[i] != 0)
		{
			if(f[i] < 0)
				update1(-f[i],1);
			if(f[i] > 0)
				update2(f[i],1);
		}
		else if(f[i] == 0)
		{
			if(cnt == 0)
			{
				++cnt;
				memset(tre1,0,sizeof(tre1));
				memset(tre2,0,sizeof(tre2));
				continue;
			}
			dp[cnt][0] = dp[cnt - 1][0] + query1(cnt);
			for(int k = 1;k <= cnt;k++)
			{
				
				int tt = query2(k) + query1(cnt - k);
				dp[cnt][k] = max(dp[cnt - 1][k],dp[cnt - 1][k - 1]);
				dp[cnt][k] += tt;
				ans = max(ans,dp[cnt][k]);
			}
			++cnt;
			memset(tre1,0,sizeof(tre1));
			memset(tre2,0,sizeof(tre2));
		}
	}
	dp[cnt][0] = dp[cnt - 1][0] + query1(cnt);
	for(int k = 1;k <= cnt;k++)
	{
		int tt = query2(k) + query1(cnt - k);
		dp[cnt][k] = max(dp[cnt - 1][k],dp[cnt - 1][k - 1]);
		dp[cnt][k] += tt;
	}
	for(int i = 0;i <= cnt;i++)
		ans = max(ans,dp[cnt][i]);
	cout << ans;
	return 0;
}

Card Game

又是一道dp题,设\(dp[i][j]\)为分到花色为i时,总共需要j张多出来的花色1来填补的方案数,其中,先预处理\(val[i][j]\)为对于同一个花色,从小到大分到数值\(i\)时,需要\(j\)个花色1来填补的方案数,可以通过dp处理出val数组,由此,也可以通过dp将dp数组处理出(对于\(dp[i][j]\),对于该花色,枚举用了k个花色1来填补,由此列出转移方程)。最后,由于对于\(val[i][j]\),可以考虑将每一种方案进行反转,即原先分给玩家1的分给玩家2,原先分给玩家2的分给玩家1,再对一一对应的那几组牌再进行分配,那么方案便由需要j个花色1来进行填补变为了多出了j个花色1可以使用,\(val[i][j]\)也变为了对于花色1,多出了j个花色1可供使用的方案数,那么最后直接统计答案即可。

#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 510;
const int MOD = 998244353;
int n,m;
int	val[N][N];
int dp[N][N];
signed main()
{
	ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
	cin >> n >> m;
	val[1][0] = 0;
	val[1][1] = 1;
	for(int i = 2;i <= m;i++)
	{
		val[i][0] = val[i - 1][1]; 
		for(int k = 1;k <= i;k++)
		{
			val[i][k] = val[i - 1][k + 1] + val[i - 1][k - 1];
			val[i][k] %= MOD; 
		}
	}
	if(n == 1)
	{
		cout << val[m][0];
		return 0;
	}
	for(int i = 2;i <= n;i++)
	{
		if(i == 2)
		{
			for(int k = m;k >= 0;k--)
			{
				dp[i][k] = val[m][k];
			}
			continue;
		}
		for(int k = m;k >= 0;k--) 
		{
			for(int j = min(m,k);j >= 0;j -= 2)
			{
				dp[i][k] += dp[i - 1][k - j] * val[m][j];
				dp[i][k] %= MOD;
			}
		}
	}
	int ans = 0;
	for(int i = 0;i <= m;i++)
		ans += val[m][i] * dp[n][i],ans %= MOD;
	cout << ans;
	return 0;
}
posted @ 2024-10-19 15:30  kanade16  阅读(71)  评论(0)    收藏  举报