Educational Codeforces Round 139 (Rated for Div. 2) 题解

A 题目链接:Problem - A - Codeforces

input:

5
9
42
13
100
111

output:

9
13
10
19
19

题意:

给定一个数 n ,求 1 ~ n 之间有多少个数,满足只有一位非0.

思路:

既然只有一位非0,那么一定是首位非0,直接计算,计算方式就是 n 的位数减1 * 9,加上 n 的最高位即可。

代码如下:

#pragma GCC optimize(3)
#include<bits/stdc++.h>
#define endl "\n"
using namespace std;
typedef long long ll;
const int mod=1e9+7;
const int N=2e5+10;

int t,n;
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	cin>>t;
	while(t--)
	{
		cin>>n;
		int ans=0;
		while(n>10)
		{
			ans+=9;
			n/=10;	
		}
		cout<<ans+n<<endl;
	}
	return 0;
}

B 题目链接:Problem - B - Codeforces

input:

6
10
codeforces
8
labacaba
5
uohhh
16
isthissuffixtree
1
x
4
momo

output:

NO
YES
NO
YES
NO
YES

题意:

给定一个长度为 n 字符串,试用以下两种操作构造该字符串:

1.在当前构造中的字符串尾添加一个字符。

2.从当前构造中的字符串中,复制任意一个连续段,添加到字符串尾。

问能否使用 n 次以内操作构造出目标字符串。

思路:

小于 n 次操作,意味着我们至少要使用一次操作2,复制至少两个字符。故我们直接以长度为2的滑动窗口遍历字符串,将所有遍历结果全都放进 map 里,看是否存在两个子串相等并且位置相距超过 1 的情况(比如 nnn 这一串,虽然12 和 23 都是 nn,但是并不能直接复制完成目标,因为中间的 n 是共用的,所以必须满足间隔超过1)。

代码如下:

#pragma GCC optimize(3)
#include<bits/stdc++.h>
#define endl "\n"
using namespace std;
typedef long long ll;
const int mod=1e9+7;
const int N=2e5+10;

int t,n;
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	cin>>t;
	while(t--)
	{
		cin>>n;
		string s;
		cin>>s;
		map<string,int> mp;
		bool f=0;
		for(int i=0;i<n-1;i++)
		{
			string k=s.substr(i,2);
		//	cout<<k<<endl;
			if(!mp.count(k))
				mp[k]=i;
			else
			{
				if(i-mp[k]>1)
				{
					f=1;
					break;
				}
			}
		}
		if(f)
			cout<<"YES"<<endl;
		else
			cout<<"NO"<<endl;
	}
	return 0;
}

C 题目链接:Problem - C - Codeforces

input:

6
3
WBB
BBW
1
B
B
5
BWBWB
BBBBB
2
BW
WB
5
BBBBW
BWBBB
6
BWBBWB
BBBBBB

output:

YES
YES
NO
NO
NO
YES

题意:

给定一个 2 * m 的格子矩形,每个格子上 "B" 代表涂黑,"W"代表不涂黑,为白色。现给出该矩形的涂色方案,问是否有一条通路满足以下两点:

1.该通路经过所有涂黑格子,且只经过一次。

2.该通路上没有任何白色格子。

思路:

两次 dfs 遍历,dfs 中对经过的黑色格子进行计数,dfs 结束后判断计数结果是否等于整个矩形黑色格子的数量。

dfs 的优先级是优先上下走,其次左右走(注意两次 memset vis 数组)

代码如下:

#pragma GCC optimize(3)
#include<bits/stdc++.h>
#define endl "\n"
using namespace std;
typedef long long ll;
const int mod=1e9+7;
const int N=2e5+10;

char c[4][N];
bool vis[4][N];
int t,n;

int func(int x,int y)
{
	vis[x][y]=1;
	if(c[3-x][y]=='B'&&!vis[3-x][y])
		return func(3-x,y)+1;
	if(y!=n&&c[x][y+1]=='B'&&!vis[x][y+1])
		return func(x,y+1)+1;
	return 1;
}

int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	cin>>t;
	while(t--)
	{
		cin>>n;
		int cnt=0;
		
		for(int i=1;i<=2;i++)
		{
			for(int j=1;j<=n;j++)
			{
				cin>>c[i][j];
				if(c[i][j]=='B')
					++cnt;
				vis[i][j]=0;
			}
		}
		bool f=0;
		if(c[1][1]=='B'&&func(1,1)==cnt)
			f=1;
		for(int i=1;i<=2;i++)
		{
			for(int j=1;j<=n;j++)
			{
				vis[i][j]=0;
			}
		}
		if(c[2][1]=='B'&&func(2,1)==cnt)
			f=1;
		if(f)
			cout<<"YES"<<endl;
		else
			cout<<"NO"<<endl;			
	}
	return 0;
}

D 题目链接:Problem - D - Codeforces

input:

4
5 15
13 37
8 9
10009 20000

output:

0
1
-1
79

题意:

一对数x,y称为 lucky ,当该对数满足 gcd (x , y) == 1。

定义 (x , y) , (x + 1, y + 1) , (x + 2, y + 2) , (x + 3, y + 3) , ...... , (x + k, y + k) 为长度 k + 1 的数对链,当该链上所有数对都为 lucky 时,称该数对链为 lucky。

给定一个数 n ,对于 n 组 x ,y,问以数对 (x , y) 为开头的 lucky 数对链的长度最大是多少。 

思路:

首先引入一个重要的结论:gcd (x , y) == gcd (x , abs (x - y))

由此可以推出:gcd (x + k , y + k) == gcd (x + k, abs (x - y)) 

所以令 d = abs (x - y),我们需要找到最小 k ,使 gcd (x + k, d) != 1 即可。

如何满足上述式子,只需要 x + k 成为某个 d 的质因数的倍数即可,所以我们对 d 分解质因数,然后对于质因数 a ,维护 a - x % a 最小值即可。

询问外预处理 1e7 内的数,为质数或非质数,之后询问时使用。

代码如下:

#pragma GCC optimize(3)
#include<bits/stdc++.h>
#define endl "\n"
using namespace std;
typedef long long ll;
const int mod=1e9+7;
const int N=1e7+10;

int t,n;
int p[N];
int prime[N];
int ind=0;
void prime_2()
{
    for(int i=2;i<=1E7;i++)
    { 
        if(!p[i])
		{
			prime[++ind]=i;
			p[i]=i;
		}
        for(int j=1;j<=ind;j++)
        {
            if(i*prime[j]>1E7) break;
            p[i*prime[j]]=prime[j];
            if(i%prime[j]==0) break;
        }
    }
}

int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	prime_2(); 
	cin>>t;
	while(t--)
	{
		int x,y;
		cin>>x>>y;
		int d=y-x;
		vector<int> v;
		if(d==1)
		{
			cout<<-1<<endl;
			continue;
		}
		if(__gcd(x,y)!=1)
		{
			cout<<0<<endl;
			continue;
		}
		int ans=10*N;
		while(d>1)
		{
			ans=min(ans,p[d]-x%p[d]);
			d/=p[d];
		}
		cout<<ans<<endl;	
	}
	return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值