Codeforces Round #805 (Div. 3)
Problem - A
题意:
给你一个数,输出它和所在位数的10的次方的差值。
思路:
从1开始不停 × 10 \times10 ×10,直到大于这个数字的时候停止,判断这个本来的数是不是就是10的次方,是就输出0,不是就相减就行。
代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e5+10;
#define PI 3.14159265358979323846;
const int INF = 0x3f3f3f3f;
void solve()
{
int n;
cin>>n;
int m=1;
while(m<n)
m*=10;
if(m==n)
cout<<0<<endl;
else
cout<<n-m/10<<endl;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int Times;
cin>>Times;
while(Times--)
solve();
return 0;
}
Problem - B
题意:
给你一个由a~z组成字符串,告诉你你每次只能取三个字母,问多少次可以取完?
思路:
每次遇到不同的字母就用数组存下,假如不同的数组数量达到了四个,就将计数器归一,同时答案+1.不能够达到3个的时候就归0,因为达到3以后可能下几个还是由找到的三个字母组成。
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e5+10;
#define PI 3.14159265358979323846;
const int INF = 0x3f3f3f3f;
bool a[26];
int b[3];
void solve()
{
memset(a,0,sizeof(a));
string s;
cin>>s;
int n=s.length();
int t=0,ans=0;;
for(int i=0;i<n;i++)
{
if(a[s[i]-'a']==0)
{
t++;
a[s[i]-'a']=1;
}
if(t==4)
{
memset(a,0,sizeof(a));
a[s[i]-'a']=1;
t=1;
ans++;
}
}
if(t>0)
ans++;
cout<<ans<<endl;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int Times;
cin>>Times;
while(Times--)
solve();
return 0;
}
Problem - C
题意:
给你一个序列,你只能从前往后走,给你q个询问,问你能不能从a数字走到b数字,改序列可能存在相同的数组。
思路:
用两个map来存这个数的最前和最后,假如a的最前还比b的最后往后,那注定无法走在一起。同时也要判断一下存不存在这个数,只要不存在就没有必要判断了。
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 2e5+10;
#define PI 3.14159265358979323846;
const int INF = 0x3f3f3f3f;
int a[maxn];
map<int,int> st;
map<int,int> ed;
map<int,bool> mp;
void solve()
{
mp.clear();
st.clear();
ed.clear();
int n,t;
cin>>n>>t;
for(int i=0;i<n;i++)
{
cin>>a[i];
if(mp.count(a[i])==0)
{
mp[a[i]]=1;
st[a[i]]=i;
}
ed[a[i]]=i;
}
while(t--)
{
int l,r;
cin>>l>>r;
if(mp.count(l)==0||mp.count(r)==0)
cout<<"NO"<<endl;
else
{
if(st[l]<=ed[r])
cout<<"YES"<<endl;
else
cout<<"NO"<<endl;
}
}
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int Times;
cin>>Times;
while(Times--)
solve();
return 0;
}
Problem - D
题意:
给你一个字符串, a a a的权值是1, b b b的权值是2,以此类推。给你一个sum,问你怎么删除这个字符串最少的个数才能使得这个字符串小于这个sum.
思路:
假如本来就是小于sum的,直接输出。假如大于的话用一个pair存它的值和位置,然后进行排序。从小到大开始加(从大到小的逆向思维),假如计数的这个num小于sum就继续加,直到大于sum.加的过程记录下位置,之后输出这些位置上的字符串。
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 2e5+10;
#define PI 3.14159265358979323846;
const int INF = 0x3f3f3f3f;
pair<int,int> a[maxn];
bool b[maxn];
void solve()
{
memset(b,0,sizeof(b));
memset(a,0,sizeof(a));
string s;
int num;
cin>>s>>num;
int n=s.length();
int sum1=0;
for(int i=0;i<n;i++)
sum1+=(s[i]-'a'+1);
if(sum1<=num)
{
cout<<s<<endl;
return;
}
for(int i=0;i<n;i++)
{
a[i].first=s[i]-'a'+1;
a[i].second=i;
}
sort(a,a+n);
int sum2=0;
for(int i=0;i<n;i++)
{
if(sum2+a[i].first<=num)
{
sum2+=a[i].first;
b[a[i].second]=1;
}
else
break;
}
for(int i=0;i<n;i++)
if(b[i]==1)
cout<<s[i];
cout<<endl;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int Times;
cin>>Times;
while(Times--)
solve();
return 0;
}
Problem - E
题意:
给你n个二元组,问你能不能把他分成两份,两份里面都含有不一样的数字。还得保证这两份不能双边不能一样。
思路:
首先里面的数字是1-n的,那么每份的数字一定会是1-n,也就是每份二元组的数量一定是n/2的。所以每个数字出现次数就是2次,每个点能到达的也就是两个点(类似于双边的图)。从一个点开始走,路是唯一的,直到遇到已经走过的点,而该点一定是出发点,这样就形成一个闭环,这个闭环点的数量为奇数的话,答案就是NO(欧拉图)。而且这道题我TLE了。原因出现在memset上面。我必须自己把vector数组进行清0。把memset(v,0,sizeof(v));
替换为for(int i=1;i<=n;i++) v[i].clear();
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 2e5+10;
#define PI 3.14159265358979323846;
const int INF = 0x3f3f3f3f;
bool vis[maxn];
vector<int> v[maxn];
void solve()
{
memset(vis,0,sizeof(vis));
//memset(v,0,sizeof(v));
int n;
cin>>n;
for(int i=1;i<=n;i++)
v[i].clear();
for(int i=1;i<=n;i++)
{
int x,y;
cin>>x>>y;
v[x].push_back(y);
v[y].push_back(x);
}
for(int i=1;i<=n;i++)
if(v[i].size()!=2)
{
cout<<"NO"<<endl;
return;
}
for(int i=1;i<=n;i++)
{
int st=i,sum=0;
while(vis[st]!=1)
{
vis[st]=1;
sum++;
if(vis[v[st][0]]!=1)
st=v[st][0];
else
st=v[st][1];
}
if(sum%2)
{
cout<<"NO"<<endl;
return;
}
}
cout<<"YES"<<endl;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int Times;
cin>>Times;
while(Times--)
solve();
return 0;
}
Problem - F
题意:
给你一个序列a与序列b。你可以对序列b里面的元素进行 × 2 \times2 ×2或者 / 2 /2 /2,通过这两种方法能不能将b序列变成a序列。注意,这个序列是没有顺序的。
思路:
奇数是必须由一个数 / 2 /2 /2才能得出来的。而偶数怎么都可以得到。比如假如一个数可以变成 3 3 3,那它一定可以变成 6 , 12 , 24 , 48 6,12,24,48 6,12,24,48.所以我们可以对a序列里面所有的数进行多次 / 2 /2 /2,除到它变成了奇数。然后对于b序列,我们不断对元素 / 2 /2 /2,找到了就匹配的a元素删掉。假如除到最后b的元素都等于0了还没找到,那就说明有个a元素没法被匹配了。则说明无法匹配。
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 2e5+10;
#define PI 3.14159265358979323846;
const int INF = 0x3f3f3f3f;
int a[maxn];
int b[maxn];
map<int,int> mp;
int fun(int a)
{
while(a%2==0)
a=a/2;
return a;
}
void solve()
{
mp.clear();
int n;
cin>>n;
for(int i=0;i<n;i++)
{
cin>>a[i];
a[i]=fun(a[i]);
mp[a[i]]++;
}
for(int i=0;i<n;i++)
{
cin>>b[i];
}
for(int i=0;i<n;i++)
{
while(b[i]!=0&&mp[b[i]]==0)
b[i]=b[i]/2;
if(mp[b[i]]==0)
{
cout<<"NO"<<endl;
return;
}
mp[b[i]]--;
}
cout<<"YES"<<endl;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int Times;
cin>>Times;
while(Times--)
solve();
return 0;
}