Educational Codeforces Round 139 (Rated for Div. 2)

题目链接

A

核心思路:这个其实就是一个简单的dp

  1. 状态定义:dp[i]表示的是\(1\sim i\)中的完美数的个数
  2. 状态划分:这个还是比较显然的,我们只需要根据最后一个位置进行状态划分就好了。就分为加了1之后的一个种类变化
  3. 状态转移方程:
  • 如果i是一个完美数,那么dp[i]=dp[i-1]+1;
  • 如果i不是一个完美数,那么dp[i]=dp[i-1];

代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
#define IOS std::ios::sync_with_stdio(0),cin.tie(0),cout.tie(0)
const int INF = 0x3fff;
const int N = 1e7+10, S = 55, M = 10000010;
int dp[N];
void Init()
{
	for (int i = 1;i < N;i++)
	{
		int y = i;
		int flag = 0;
		while (y)
		{
			if (y % 10 != 0)
				flag++;
			y /= 10;
		}
		if (flag == 1)
			dp[i] = dp[i - 1] + 1;
		else
			dp[i] = dp[i - 1];

	}
}
void solve()
{
	int n;
	cin >> n;
	cout << dp[n]<<endl;
}
int main()
{
	Init();
	int T;
	cin >> T;
	while (T--)
	{
		solve();
	}
}

PS:还有另外一种做法就是找规律,不过有时候找不出就有点坐牢。所以还是推荐第一种做法。


B

核心思路:其实这个很简单我们只需要找出一对字符串是相等的。那么就必然是相等的 ,刚开始粗心读错了题目。实际上那个n我们字符串的长度。所以我们老样子先从一般出发,先考虑三个字符的情况也就是s[i],s[i-1],s[i-2].这里我们可以采用mp来帮助我们存储某些字符是否出现过。代码还是比较简单的.

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 1e6;
int a[N];
int b[N];
bool used[26][26];
void solve()
{
	for (int i = 0;i <= 25;i++)
		for (int j = 0;j <= 25;j++)
			used[i][j] = false;
	int n;
	string s;
	cin >> n >> s;
	for (int i = 1;i <n;i++)
	{
		if (used[s[i] - 'a'][s[i - 1] - 'a'])
		{
			cout << "YES" << endl;
			return;
		}
		else if (i!=1)
			used[s[i - 1] - 'a'][s[i - 2] - 'a'] = true;
	}
	cout << "NO" << endl;
	return;
}
int main()
{
	int T;
	cin >> T;
	while (T--)
	{
		solve();
	}
}

C

核心思路:其实这个题目的意思也就是要求我们把地图上面的B全都走完,并且不允许我们回退。所以其实我们的合法路径只有这种形式:

.   . . .   .
.   .   .   .
. . .   . . .

所以我们先竖着把这些B全都走完,在横向移动。

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 1e6;
int a[N];
int b[N];
bool used[26][26];
void solve()
{
	int n;
	string s[2];
	cin >> n;
	cin >> s[0] >> s[1];
	for (int t = 0;t < 2;t++)
	{
		int x = t;
		int flag = 1;
		for (int i = 0;i < n;i++)
		{
			if (s[x][i] != 'B')
				flag = 0;
			if (s[!x][i] == 'B')
				x ^= 1;
		}
		if (flag)
		{
			cout << "YES" << endl;
			return;
		}
	}
	cout << "NO" << endl;

}
int main()
{
	int T;
	cin >> T;
	while (T--)
	{
		solve();
	}
}

D

核心思路:这个题目其实也是不难的,反正数论的 题目我最喜欢做了。但是有一个需要注意的是这里会卡输入和输出如果我们采用的是普通的质数筛,所以需要记得关闭输入和输出流。接下来分析一下。首先我们可以联想一下辗转相除法来对这个题目进行一个化简:\(gcd(x+k,y+k)=gcd(y+k,y-x)=1\),然后我们就会发现y-x=d是个常数,而我们的题目是要我们求最小的k使得y+k和d互质,于是我们可以转换为他们的临界条件:也就是他们不互质的时候。换句话说就是y+k可以被d整除。也就是也就是我们对d分解质因数p,然后可以得书出\(y+k=0(\mod)\),这样搞出来我们会发现这是个负数,也就是k=-y.所以我们需要把他转换一下,也就是k=(p-y%p)%p,这是我们最基本的转为最小正整数的一个方法.

#include <iostream>
 #include <cstring>
 #include <algorithm>
 #include <cmath>
 
 using namespace std;
 typedef pair<int, int> PII;
 const int N = 3200, M = 2 * N, INF = 0x3f3f3f3f;
 int n, m, a[N];
 int p[N], pe[N], primes[10000010], cnt;
 bool st[10000010];
 
 void init() {
     for (int i = 2; i < N; i++ ) {
         if(!st[i]) primes[cnt++ ] = i;
         for (int j = 0; primes[j] * i < N; j++ ) {
             st[primes[j] * i] = true;
             if(i % primes[j] == 0) break;
         }
     }
 }
 
 void solve()
 {
     int a, b;
     cin >> a >> b;
     if(a > b) swap(a, b);
     int t = b - a;
     
     int d = __gcd(a, b);
   if (d > 1) {
     cout << 0 << '\n';
     return ;
   }
   
     int cur = 0, ans = INF;
     while(primes[cur] <= sqrt(t)) {
         if(t % primes[cur]) {
             cur++ ;
             continue;
         }
         while(t % primes[cur] == 0) t /= primes[cur];
         ans = min(ans, primes[cur] - a % primes[cur]);
         cur++ ;
     }
     if(t > 1) ans = min(ans, t - a % t);
     
     if(ans == INF) ans = -1;
     cout << ans << '\n';
     
 }
 
 signed main() {
     ios::sync_with_stdio(0),cin.tie(0);
     // freopen("input.txt", "r", stdin);
     init();
     int T = 1;
     cin >> T;
     while(T -- ) solve();
     return 0;
 }              
posted @ 2022-12-13 23:32  努力的德华  阅读(83)  评论(0)    收藏  举报