第一次题解记录
Codeforces Round #828 (Div. 3)
第一次使用C++语言解题,可能存在很多不简洁的地方。
A
注意本题可用相同的字母代替数字,因此采用数字作为key值。
#include<vector>
#include<math.h>
#include<algorithm>
#include<string>
#include<map>
#include<iostream>
using namespace std;
int main()
{
int num;
cin>>num;
for(int i = 0;i<num;i++)
{
int number;
cin>>number;
vector<int> a(number);
for(int j = 0;j<number;j++)
cin>>a[j];
char b[number];
cin>>b;
map<int,char> mymap;
for(int j = 0;j<number;j++)
{
if(mymap.count(a[j])==0)
mymap[a[j]] = b[j];
else if(mymap.count(a[j])==1&&mymap[a[j]]!=b[j])
{
cout<<"NO"<<endl;
break;
}
if(j==number-1) cout<<"YES"<<endl;
}
}
}
B
本题需要运用简单的数学知识,用模拟反复求总和会超时
#include<bits/stdc++.h> //这个头文件方便
typedef long long ll; //long long 太长
using namespace std;
int main()
{
ll tc;cin>>tc;while(tc--) //tc --test case
{
ll num,q;
cin>>num>>q;
ll sum =0,even = 0,odd = 0;
for(int i = 0;i<num;i++)
{
ll tmp;
cin>>tmp;
if(tmp%2==0) even++;
else odd++;
sum +=tmp;
}
while(q--){
ll q1,number;
cin>>q1>>number;
if(q1==0){
sum+=even*number;
if(number%2==1){
odd +=even;
even = 0;
}
}else{
sum +=odd*number;
if(number%2==1)
{
even+=odd;
odd = 0;
}
}
cout<<sum<<endl;
}
}
}
C
本题运用了双指针的方式,代码可能复杂了
#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
int main()
{
ll tc;cin>>tc;while(tc--)
{
int len;
char c;
cin>>len>>c;
char str[len];
cin>>str;
if(c=='g'){
cout<<"0"<<endl;
continue;
}
int ix1 = 0,ix2 = 0,max1 = 0;
while(ix1<len&&ix2<len){
while(str[ix1]!=c)
{
ix1++;
}
ix2 = ix1+1;
while(str[ix2]!='g'&&ix2<len)
{
ix2++;
}
if(ix2>=len) break;
max1 = max(max1,ix2-ix1);
ix1 = ix2+1;
}
if(ix2>=len){
ix2 = 0;
while(str[ix2]!='g'&&ix2<len)
{
ix2++;
}
max1 = max(max1,len-(ix1-ix2));
}
cout<<max1<<endl;
}
}
D
本题需要运用一定的数学知识
#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
int main()
{
ll tc;cin>>tc;while(tc--){
int num;cin>>num; //num表示为有num个数,并且需要结果能被num个2整除
int ta[num+2]={},cnt=0; //ta用于存贮该索引i能被x个2整除
//注意定义完数组需要赋值。。如int a[10]={} 本次去掉{}得不到对应的答案
for(int i = 1;i<=num;i++)
{
int tmp = i;
//因为需要结果为2的倍数,那么乘上的索引必须也是2的倍数,不然是没有意义的操作
while(tmp%2==0) tmp/= 2,ta[i]++; //统计该索引能被几个2整除
int number;
//cnt 用于统计当前输入的数据能被几个2整除
cin>>number;while(number%2==0) cnt++,number/=2;
}
int ans=0,now = 1;
//注意默认的排序是小大的排序
sort(ta+1,ta+1+num,greater<int>()); //贪心用于此处,从大到小的排
while(cnt<num)
{
if(now<=num) cnt+=ta[now],now++,ans++;
else break;
}
if(cnt>=num) cout<<ans<<endl; //当cnt>=num 就意味着肯定存在一个ta[i]+cnt==num
else cout<<"-1"<<endl;
}
return 0;
}
E1
本题需要掌握gcd(欧几里得算法), gcd(a,b) = gcd(b, a mod b)
注意能用long long不用int 像这题用int 过不了用例9
题意:在(a,c]中找到x,在(b,d]中找到y,使得x * y能被a * b整除
思路:如果x * y能被a * b整除,那么y能够被(a * b/(a * b与x的最大公因子))整除即图片的式子将图片的公式设为s,去寻找s的整数倍是否在(b,d]的范围中
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int main()
{
int tc;cin>>tc;while(tc--)
{
ll a,b,c,d;
cin>>a>>b>>c>>d;
ll i;
for(i = a+1;i<=c;i++)
{
ll s = (a*b)/__gcd(a*b,i); //__gcd头文件#include< algorithm> 求最大公因数
if(b/s!=d/s) { //如果b和d相差一个s那么有这样的一对 能够迅速加快
cout<<i<<" "<<(b/s+1)*s<<endl;
break;
}
}
if(i==c+1) cout<<"-1 -1"<<endl; //遍历完毕则未找到
}
}