完整版的题解
A题
这道题可以拿字符串写,如果字符串的长度只有2,且组成该字符串的两个字符相同那它就是好数
#include<bits/stdc++.h>
using namespace std;
#define endl '\n'
int main(){
string a;
cin>>a;
if (a.length()==2 && a[0]==a[1])cout<<"Yes";
else cout<<"No";
return 0;
}
B题
字符串有三个字符,直接输出第一个和第三个就行
#include<iostream>
using namespace std;
#define endl '\n'
int main(){
string a;
cin>>a;
cout<<a[0]<<a[2];
return 0;
}
C题
如果x,y,n相等,那他们的最大公约数就是n本身,但题目里说了x和y不相等,那我们令y=2x就好了
#include<bits/stdc++.h>
using namespace std;
#define endl '\n'
int main(){
int q;
cin>>q;
while (q--){
long long a;
cin>>a;
cout<<a<<' '<<a*2<<endl;
}
return 0;
}
D题
暴力就能过,但是我也只会暴力
把数的每个数位分开,其中包含x就计数即可
#include<bits/stdc++.h>
using namespace std;
#define endl '\n'
int main(){
int n,x,ans=0;
cin>>n>>x;
for (int i = 1; i <= n; ++i) {
int temp=i;
while (temp){
if (temp%10==x)ans++;
temp/=10;
}
}
cout<<ans;
return 0;
}
E计算进位
两个数字相加,会不会出现进位的情况 现在就是小学的加法问题 eg: 1563+654 从尾项开始(即3+4)这个位加完后往前加直到5+6
为什么是5+6? 可以看到这两个数分别是三位和四位 那这个四位的数加一个三位的如果变成了五位,那么这两个数在第三位肯定就进位了,那我们只算到第三位判断是否需要进位
这里可以看出十位(5+6=11)和百位涉及进位 ok了,有这个基础知识就可以开肝
#include<iostream>
#include<string>
#include<algorithm>//reverse的头
using namespace std;
int main()
{
string a,b;
cin>>a>>b;
int x=0;
int len=a.size()>b.size()?b.size():a.size();//找短的那个的长度
reverse(a.begin(),a.end());//反转字符串
reverse(b.begin(),b.end());
for(int i=0;i<len;i++)
{
if((a[i]-'0')+(b[i]-'0')>=10)//判断是否进位
{
x=1;//进位的情况,标记x=1
break;
}
}
if(x)cout<<"Hard";
else cout<<"Easy";
return 0;
}
F可编程拖拉机比赛
题目意思: 给你一个数,你要计算这个数的0.1,0.2,0.3(对应分别拿金,银,铜的人数),最后拿总数减去拿这几种牌子的人就是拿铁牌的人 分别向上向下取整值为多少,然后计算每个数的向上向下取整后,根据变化,算多少人的奖牌应该换 题目样例115,这里以115为例:
向下取整 | 11 | 23 | 34 | 115-11-23-34=47 |
向上取整 | 12 | 23 | 35 | 45 |
接下来展示换牌的计算方式 (x[0]为11,y[0]为23,z[0]为34,w[0]为47,w[1]为35,其他类推) 原本按照向下取整发,实际按照向上发
ans1=银->金=x[1]-x[0]
y[1]-y[0]=银牌变化量=银牌增加量-银牌减少量=(铜->银)-(银->金) ans2=(铜->银)=(银->金)+(y[1]-y[0]);
z[1]-z[0]=铜牌变化量(后面和银牌变化量开始都一样) 或者 ans3=(铁->铜)就是铁牌变化量 终于写完了,上代码
#include<bits/stdc++.h>
using namespace std;
int arr[21],brr[21],crr[21];
int main()
{
int n;
cin>>n;
double n1=n;
//这边存int n,n/10就是直接向下取整
//floor也能直接向下取整(取整得要对浮点型数据才有用,整形没必要)
int x[2]={0,0},y[2]={0,0},z[2]={0,0},w[2]={0,0};
int ans[4];
for(int i=0;i<4;i++)ans[i]=0;
x[0]=n/10;
y[0]=(n*0.2);
z[0]=n*0.3;
w[0]=n-x[0]-y[0]-z[0];
x[1]=ceil(n1/10);
y[1]=ceil(n1*0.2);
z[1]=ceil(n1*0.3);
w[1]=n-x[1]-y[1]-z[1];
ans[0]=fabs(x[1]-x[0]);
ans[1]=fabs(y[1]-y[0]);
ans[2]=fabs(z[1]-z[0]);
ans[3]=fabs(w[1]-w[0]);
// cout<<x[0]<<" "<<x[1]<<endl;
// cout<<y[0]<<" "<<y[1]<<endl;
// cout<<z[0]<<" "<<z[1]<<endl;
// cout<<w[0]<<" "<<w[1]<<endl;
//
// for(int i=0;i<4;i++)cout<<"ans["<<i<<"]="<<ans[i]<<" ";
// cout<<endl;
cout<<ans[0]<<" "<<ans[1]+ans[0]<<" "<<ans[3]<<" ";
return 0;
}
G题
法1(队列法)
简单来说就是一个边出边存的小问题 用经典的队列解决约瑟夫环 https://blog.csdn.net/m0_51506743/article/details/124004350 有了这个前置知识就是在该问题基础上先走k次 比较简单就直接上代码了
#include<bits/stdc++.h>
using namespace std;
int main()
{
int n,k,m;
cin>>n>>k>>m;
queue<int>q;
for(int i=0;i<n;i++)
{
q.push(i);
}
int f=0;
while(k--)
{
f=q.front();
q.pop();
q.push(f);
}
int j=1;
while(q.size()!=1)
{
if(j==m)
{
f=q.front();
q.pop();
j=1;
}
else{
f=q.front();
q.pop();
q.push(f);
j++;
}
}
cout<<q.front();
return 0;
}
法2(公式法)
先常规的上连接:https://blog.csdn.net/u011500062/article/details/72855826 ok了啊兄弟们 直接上代码
#include <iostream>
using namespace std;
void solve(int n,int k,int m) {
int p=0;
for(int i=2;i<=n;i++) p=(p+m)%i;
cout<<(p+k)%n<<endl;;
}
int main()
{
int n,k,m;
cin >> n >> k >> m;
solve(n,k,m);
return 0;
}
H题
前置知识
- gcd(m,n)=n?gcd(n,m%n):m;
- lcm=m∗n/gcd(m,n)
首先,这题真的简单
gcd与lcm,这边提供两种思路及3种AC代码。
首先,我们看题目不难发现,一共给了2种数据
分别是日期的gcd值和lcm值。
解法1
首先我们不难想到,全部搜一遍,查看是否存在多个日期的gcd和lcm与目标相同。
于是下面的代码
#include<bits/stdc++.h>
#include<cmath>
using namespace std;
const int N =1e6+10;
typedef pair<int,int> PII;
typedef long long ll;
bool pd(int a,int b){
if(a==1||a==3||a==5||a==7||a==8||a==10||a==12){
if(b<=0||b>31)return false;
}
else if(a==2){
if(b<=0||b>29)return false;
}
else{
if(b<=0||b>30)return false;
}
return true;
}
void solve(){
int n,m;
cin>>n>>m;
vector<PII>vt;
for(int i=1;i<=12;i++){
for(int j=1;j<=31;j++){
if(lcm(i,j)==n&&gcd(i,j)==m){
vt.push_back({i,j});
}
}
}
for(int i = vt.size()-1;i>=0;i--){
int a = vt[i].first,b=vt[i].second;
if(pd(a,b)==false){
vt.erase(vt.begin() + i);
}
}
if(vt.size()==1){
cout<<"YES"<<endl;
}
else{
cout<<"NO"<<endl;
}
}
int main(){
ios::sync_with_stdio(0);
cin.tie(0);
int tt = 1;
cin>>tt;
while(tt--){
solve();
}
return 0;
}
那么这种方法太慢了,平均每组样例的解决时间复杂度是O(n∗m)O(n∗m),也就是大约要12*30次判断才能做出一组数据。
解法2,稍稍优化一下思路
上面的判断实在是太复杂了,每一个都去判断。
但是,有没有一种可能,
其实月份和日期随便选一个去判断,另一个其实同时也判断出来了。
由于已知 gcd∗lcm=date∗month,同时,令t为月份日期的积,我们用i去遍历月份,t/i其实就是日期。
接下来只需要判断 i 和 t/i 的gcd和lcm是否符合题目给出的,如果符合就用cnt计数。
遍历完12个月之后,判断 cnt=1 ,符合这个条件说明是唯一的,否则就是存在其他日期符合条件。
上AC 代码↓
#include <bits/stdc++.h>
#define int long long
using namespace std;
void zxy()
{
int n,m;cin>>n>>m;
int num = n * m;
int month[12] = {31,29,31,30,31,30,31,31,30,31,30,31};
int cnt = 0;
for(int i=1;i<=12;i++)
{
if(num%i==0&&num/i<=month[i-1]&&gcd(i,num/i)==m&&lcm(i,num/i)==n) cnt ++;
}
if(cnt == 1) cout<<"YES"<<endl;
else cout<<"NO"<<endl;
}
signed main()
{
int t; cin>>t;
while(t --) zxy();
return 0;
}
解法3(暴力打表)
这个是出题时候写的解法,应该是本题目在数据量较大的情况下比较好的解法。
我们先建立一个二维数组,横纵坐标分别是gcd和lcm,一个1000,一个40足够了。
接下来预处理数据,遍历每个日期,计算gcd和lcm,并在对应的下标++,用于统计。
接下来只需要读入gcd和lcm,然后去数组里面查询是否唯一即可。
参考代码↓
#include "bits/stdc++.h"
using namespace std;
int main()
{
int mp[373][32];
memset(mp,0,sizeof mp);
for(int i=1;i<13;i++)
{
for(int j=1;j<32;j++)
{
mp[lcm(i,j)][gcd(i,j)]++;
}
}
int q;cin>>q;
while(q--)
{
int l,g;cin>>l>>g;
if(mp[l][g]==1)cout<<"YES"<<endl;
else cout<<"NO"<<endl;
}
return 0;
}
记得补题
I题
答案是3181,代码直接这么写就行了↓
#include<bits/stdc++.h>
using namespace std;
#define endl '\n'
int main(){
cout<<3181;
return 0;
}
我的结果是模拟出来的,除了模拟我也不会别的
先设定一个长度为9的数组,填充上2021,模拟每种卡片的数量,用n表示当前试图拼的数字
如果某种卡片数量已经到0了,那就拼不出n,能拼出来最大的就是n-1
#include<bits/stdc++.h>
using namespace std;
#define endl '\n'
int main(){
int arr[9];
fill(arr,arr+9,2021);
int n=0;
while (1){
n++;
cout<<n<<endl;
int temp=n;
while (temp){
if (arr[temp%10]<=0){cout<<n-1;return 0;}
else arr[temp%10]--;
temp/=10;
}
}
}