Codeforces 685 Div2 A~D

A. Subtract or Divide(AC)

题意:猜想n可以通过若干次的下面两个操作变为1,输出最小操作次数
1:减去1
2:除以除自身以外的因子

思路:找规律,分奇数和偶数讨论,n<3特判输出

#include<bits/stdc++.h>
using namespace std;
 
 
int main()
{
    
    
	int n,t;
	cin>>t;
	while(t--)
	{
    
    
		int cnt=0;
		cin>>n;
		if(n==1)cout<<0<<endl;
		else if(n==2)cout<<1<<endl;
		else if(n%2==0||n==3)cout<<2<<endl;
		else if(n%2==1&&n>3)cout<<3<<endl;
		
	}	
	return 0;
} 

反思:多手动模拟,比样例多模拟一些,找找规律,做这题的时候模拟了1~10

B. Non-Substring Subsequence(AC)

题意,给定字符串和要匹配的子串,从原字符串中依次找出不完全连续的字符来组成子串

思路:从左到右暴力匹配感觉不大行,所以以子串左右端点为起点,向两边搜索直到边界。只需要左边区域有和左端点字符相同的或者右边区域有和右端点相同的即可(标答的思路差不多,子串第一个字符不是第一次出现,或者最后一个字符不是最后一次出现)

#include<bits/stdc++.h>
using namespace std;


int main()
{
    
    
	int t,n,q;
	char s[500];
	cin>>t;
	while(t--)
	{
    
    
		cin>>n>>q;
		cin>>s+1;
		int l,r,lt,rt;
		while(q--)
		{
    
    
			cin>>l>>r;
			lt=l,rt=r;
			int flag=0;
			if(r-l+1<2)puts("NO");
			else
			{
    
    
				while(lt)
				{
    
    
					if(s[lt-1]!=s[l])lt--;
					else
					{
    
    
						puts("YES");
						flag=1;
						break;
					}
				}
				while(rt<=n&&!flag)
				{
    
    
					if(s[rt+1]!=s[r])rt++;
					else
					{
    
    
						puts("YES");
						flag=1;
						break;
					}
				}
				if(!flag)puts("NO");
			}
		}
		
		
	}
	return 0;
} 

反思:匹配不一定要从左到右,可以选取参考点向两边匹配

C. String Equality(补题)

给定两个字符串,两种操作
1任意调换相邻两个顺序
2若有长度>=k的连续相同子串,可以把这段子串替换为字母表下一个字符(z除外)

操作可以任意排序,所以我们主要考虑每个字符出现频率。然后主要看能不能转换完全,原本考虑匹配频率相同的子串来转换,但有漏洞,主要是不完全转换和转换成哪个字符的问题(因为涉及要更新频率)。这边按字母表顺序来遍历转化,主要看代码吧,有点类似加减法进位,看当前位是否有不能转化的,如果可以转化就更新加到下一位。

#include<bits/stdc++.h>
using namespace std;

map<char,int>ma,mb;
int main()
{
    
    
	int t,n,k;
	string a,b;
	cin>>t;
	while(t--)
	{
    
    
		cin>>n>>k>>a>>b;
		ma.clear();
		mb.clear();
		for(int i=0;a[i];i++)ma[a[i]]++;
		for(int i=0;b[i];i++)mb[b[i]]++;
		int f=0;
		for(char i='a';i<='z';i++)
		{
    
    
			if(ma[i]<mb[i]||(ma[i]-=mb[i])%k)f=1;
			ma[i+1]+=ma[i];
		}
		if(f)puts("No");
		else puts("Yes");
	}
	return 0;
} 

D - Circle Game(AC)

题意,起点(0,0)给定范围半径d,每次必须在x或者y轴增加k,两个人轮流操作,每次操作后位置不能超过半径为d的圆直到有一方无法走动即可判断胜负,两人都用最好策略

思路:既然两人都用最好策略那么就要尽可能选择走得近的。现在每次操作可以选x方向或者y方向,哪个小选哪个就行了啊

#include<bits/stdc++.h>
using namespace std;

int main()
{
    
    
	int t;
	double d,k;
	cin>>t;
	while(t--)
	{
    
    
		bool p=0;
		double x=0,y=0;
		cin>>d>>k;
		while(1)
		{
    
    
			if(x>=y)y+=k;
			else x+=k;
			if(x*x+y*y>d*d)
			{
    
    
				if(!p)
				{
    
    
					puts("Utkarsh");
					break;
				}
				else
				{
    
    
					puts("Ashish");
					break;
				}
			}
			p=!p;
		}
	}
	return 0;
}

反思:有点贪心操作,关键是如何在几个操作中选出最好的。min(操作1,操作2)即可

猜你喜欢

转载自blog.csdn.net/qq_39354847/article/details/109923397