当前位置: 代码迷 >> 综合 >> 1114 - 2021级ACM预科队 训练赛 第21场 结构体位运算
  详细解决方案

1114 - 2021级ACM预科队 训练赛 第21场 结构体位运算

热度:62   发布时间:2023-11-23 01:26:26.0

问题 A: 整数幂

题目描述
判断一个数N是不是2的整数幂,比如8=2^3,输出“Yes”,而9不是2的整数幂,输出“No”。
输入
第一行一个整数T(1≤T≤1000),表示有T组数据。
随后T行,每行一个正整数N(N在int范围内)。
输出
输出“Yes”或“No”。
样例输入
1
8
样例输出
Yes

结论题,知道n&(n-1)判断是否整除就行

#pragma GCC optimize(1)
#pragma GCC optimize(2)
#pragma GCC optimize(3,"Ofast","inline")
# include<iostream>
# include<iomanip>
# include<algorithm>
# include<cmath>
# include<cstdio>
# include<set>
# include<stack>
# include<queue> 
# include<map>
# include<string>
# include<cstring> # define eps 1e-9
# define fi first
# define se second
# define ll long long
# define int ll
// cout<<fixed<<setprecision(n) 
using namespace std;typedef unsigned long long ull;
typedef pair<int,int > PII; 
const int mod=1e9+7;
const int MAX=3e5+10;
const int Time=86400;
const int X=131;
const int inf=0x3f3f3f3f;
const double PI = 1e-4;
double pai = 3.14159265358979323846; 
priority_queue<int,vector<int>,less<int>> q;int n,t,T;
char a[MAX];void solve(){
    cin >> n;if((n & (n-1) )== 0 ) cout<<"Yes\n";else cout<<"No\n";
}
signed main(){
      std::ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);cin >> T;while(T--){
    solve();}return 0;
}

问题 B: 二进制半整数

题目描述
一个数n如果能表示成2i+2j,那么它就是个二进制半整数。你能判断一个数是否是二进制半整数吗?
输入
第一行输入t(1≤t≤1000),表示数据组数。
接下来t行,输入一个数n(1≤n≤1000000000)。
输出
输出t行,每行yes或no表示是否是二进制半整数。
样例输入 Copy
2
4
7
样例输出 Copy
yes
no
本题提供三种思路
1.根据题意知道n在10^9以内,我们枚举双层for(枚举0-30)暴力求解满足的i,j即可,复杂度为O(T * 30^2),这个复杂度肯定能过
2.根据2^i + 2^j ,我们可以化简一下2^i(1+2 ^ j-i) 然后枚举i判断即可,这种方法不好写,建议暴力还不如第一种
3.我们思考一下什么时候才满足半整数?很容易想到一点,如果一个n展开二进制下满足1个或者2个1那它就是满足半整数的

为什么呢?2个1很容易想到;1个1可以由两个1得到比如64 可以由两个32得来
知道结论后,这题就很容易了!就是找1的个数。不过我们要特判 <= 3的情况,看代码具体理解一下吧。

#pragma GCC optimize(1)
#pragma GCC optimize(2)
#pragma GCC optimize(3,"Ofast","inline")
# include<iostream>
# include<iomanip>
# include<algorithm>
# include<cmath>
# include<cstdio>
# include<set>
# include<stack>
# include<queue> 
# include<map>
# include<string>
# include<cstring> # define eps 1e-9
# define fi first
# define se second
# define ll long long
# define int ll
// cout<<fixed<<setprecision(n) 
using namespace std;typedef unsigned long long ull;
typedef pair<int,int > PII; 
const int mod=1e9+7;
const int MAX=3e5+10;
const int Time=86400;
const int X=131;
const int inf=0x3f3f3f3f;
const double PI = 1e-4;
double pai = 3.14159265358979323846; 
priority_queue<int,vector<int>,less<int>> q;int T,n;
void solve(){
    int cnt = 0;cin >> n;if(n <= 3) {
    cout<<"no\n";return;}while(n) {
    if(n & 1) cnt++;n >>= 1;}//也可以用下面这种写法判断1个数//while(n) n = n & (n-1),cnt++;if(cnt == 1 || cnt == 2) cout<<"yes\n";else cout<<"no\n";
}
signed main(){
      std::ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);cin >> T;while(T--){
    solve();}return 0;
}

问题 C: 十进制转十六进制

题目描述
将十进制数转化为相应的十六进制数
样例输入 Copy
10
样例输出 Copy
A

直接看代码理解吧,应该不难

#pragma GCC optimize(1)
#pragma GCC optimize(2)
#pragma GCC optimize(3,"Ofast","inline")
# include<iostream>
# include<iomanip>
# include<algorithm>
# include<cmath>
# include<cstdio>
# include<set>
# include<stack>
# include<queue> 
# include<map>
# include<string>
# include<cstring> # define eps 1e-9
# define fi first
# define se second
# define ll long long
# define int ll
// cout<<fixed<<setprecision(n) 
using namespace std;typedef unsigned long long ull;
typedef pair<int,int > PII; 
const int mod=1e9+7;
const int MAX=3e5+10;
const int Time=86400;
const int X=131;
const int inf=0x3f3f3f3f;
const double PI = 1e-4;
double pai = 3.14159265358979323846; 
priority_queue<int,vector<int>,less<int>> q;int n,t;
char a[MAX];signed main(){
      std::ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);cin >> n;if(n == 0) cout<<0;while(n){
    int x = n % 16;if(x >= 0 && x <= 9) a[t++] = x + '0';else a[t++] = x + 55;n /= 16;}for(int i = t - 1 ; i >= 0 ; i -- )cout<<a[i];return 0;
}

问题 D: 十进制转N进制

题目描述
十进制数转N进制数。
样例输入 Copy
3 2
样例输出 Copy
11

#include<stdio.h>
#include<iostream>
#include<cmath>
#include<string>
#include<iomanip>
#include<cstring>
#include<ctype.h>
#include<algorithm>
using namespace std;
int main()
{
    char a[100]={
    '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'};string s;int n,t,k=0;cin>>n>>k;if(n==0)cout<<0;else{
    while(n){
    t=n%k;s+=a[t];n/=k;}reverse(s.begin(),s.end());cout<<s;}}

问题 E: 十进制小数转N进制

题目描述
十进制小数x转为N进制数。转换的方法是“乘N顺序取整。”例如x=0.8125 ,N=8,输出0.64。(保证小数<1,转化后的小数可用精确位为20位)
样例输入 Copy
0.8125 8
样例输出 Copy
0.64

#include<stdio.h>
#include<iostream>
#include<cmath>
#include<string>
#include<iomanip>
#include<cstring>
#include<ctype.h>
#include<algorithm>
using namespace std;
int main()
{
    
float x;
int n,k=0;
cin>>x>>n;
cout<<"0.";
while(x!=0)
{
       x=x*n;cout<<(int)x;int y=(int)x;x=x-y;k++;if(k==20)break;
}}

问题 F: N进制转换为十进制

题目描述
N进制整数转换为十进制
输出

样例输入 Copy
2 11
样例输出 Copy
3

#include<stdio.h>
#include<iostream>
#include<cmath>
#include<string>
#include<iomanip>
#include<cstring>
#include<ctype.h>
#include<algorithm>
using namespace std;
long long n,s=0;
int main()
{
    string x; 
cin>>n>>x;
int k=0;
for(int i=x.size()-1 ;i>=0;i--)
{
    char t=x[i];if(isdigit(t))s=s+(t-'0')*pow(n,k++);elses+=(t-'A'+10)*pow(n,k++);
}
cout<<s;
}

问题 G: N进制小数转十进制

题目描述
输入N进制小数,转十进制
样例输入 Copy
2 0.111
样例输出 Copy
0.875

#include<stdio.h>
#include<iostream>
#include<cmath>
#include<string>
#include<iomanip>
#include<cstring>
#include<ctype.h>
#include<algorithm>
using namespace std;
long long n;
float s=0;
int main()
{
    string x; 
cin>>n>>x;
int k=-1;
for(int i=2 ;i<x.size() ;i++)
{
    char t=x[i];if(isdigit(t))s=s+(t-'0')*pow(n,k--);elses+=(t-'A'+10)*pow(n,k--);
}
cout<<s;
}

问题 H: N进制数加法

题目描述
N(N<37)进制数加法运算问题,即从键盘输入一个小于37的正整数N,再输入符合要求的两个N进制数,求两者之和,输出结果仍为N进制数。

#include<stdio.h>
#include<iostream>
#include<cmath>
#include<string>
#include<iomanip>
#include<cstring>
#include<ctype.h>
#include<algorithm>
using namespace std;
long long n;
int s=0;
int main()
{
    string x,y,c; cin>>n;cin>>x>>y;int k=0;reverse(x.begin() ,x.end() );reverse(y.begin() ,y.end() );int x1;x1=max(x.size() ,y.size() );int f=0;for(int i=0;i<x1;i++){
    if(i<x.size()&&i<y.size() ){
    if(isdigit(x[i])&&isdigit(y[i]))s=x[i]-48+y[i]-48;  elseif(isdigit(x[i])&&!isdigit(y[i]))s=x[i]-48+y[i]-'A'+10;  elseif(!isdigit(x[i])&&isdigit(y[i])){
    s=x[i]-'A'+10+y[i]-48;}elseif(!isdigit(y[i])&&!isdigit(x[i]))s=x[i]-'A'+10+y[i]-'A'+10;}elseif(i<x.size()&&i>=y.size() ){
    if(isdigit(x[i])) s=x[i]-48;elses=x[i]-'A'+10;}elseif(i<y.size() &&i>=x.size() ){
    if(isdigit(y[i])) s=y[i]-48;elses=y[i]-'A'+10;}if(s+f>=n){
    if(s-n+f<10)c[k++]=s-n+f+48;elsec[k++]=s-n+'A'-10+f;f=1;}else{
    if(s<10)c[k++]=s+'0'+f;elsec[k++]=s+'0'+f-'A'+10;f=0;}}c[k++]=f+48;if(c[k-1]!='0')printf("%c",c[k-1]);
for(int i=k-2;i>=0;i--)
{
    
printf("%c",c[i]);
}

问题 I: 二进制分类

题目描述
若将一个正整数化为二进制数,在此二进制数中,我们将数字1的个数多于数字0的个数的这类二进制数称为A类数,否则就称其为B类数。
例如:
(13)10=(1101)2,其中1的个数为3,0的个数为1,则称此数为A类数;
(10)10=(1010)2,其中1的个数为2,0的个数也为2,称此数为B类数;
(24)10=(11000)2,其中1的个数为2,0的个数为3,则称此数为B类数;
程序要求:求出a~b之中全部A、B两类数的个数。
输入
两个整数,即a和b。
输出
一行,包含两个整数,分别是A类数和B类数的个数,中间用单个空格隔开。
样例输入 Copy
1 1000
样例输出 Copy
538 462

#include<stdio.h>
#include<iostream>
#include<cmath>
#include<string>
#include<iomanip>
#include<cstring>
#include<ctype.h>
#include<algorithm>
using namespace std;
long long n;
int s=0;
int main()
{
    
long long a,a1=0,b1=0,b,a2=0,b2=0;
cin>>a>>b;
for(int i=a;i<=b;i++)
{
    int k;a1=0;b1=0;int j=i;while(j){
    k=j%2;if(k==1)a1++;elseb1++;j/=2; }if(a1>b1)a2++;elseb2++;
}
cout<<a2<<" "<<b2;
}

问题 K: K进制转L进制

题目描述
输入K进制的正整数N,将之转为L进制后输出(N<1000000;L,K<=16)有多组数据。
输入
三个整数K,N,L
输出
输出N的L进制数。
样例输入 Copy
8 10 2
10 10 16
样例输出 Copy
1000
A

思路:先转10进制再转L进制

#pragma GCC optimize(1)
#pragma GCC optimize(2)
#pragma GCC optimize(3,"Ofast","inline")
# include<iostream>
# include<iomanip>
# include<algorithm>
# include<cmath>
# include<cstdio>
# include<set>
# include<stack>
# include<queue> 
# include<map>
# include<string>
# include<cstring> # define eps 1e-9
# define fi first
# define se second
# define ll long long
# define int ll
// cout<<fixed<<setprecision(n) 
using namespace std;typedef unsigned long long ull;
typedef pair<int,int > PII; 
const int mod=1e9+7;
const int MAX=3e5+10;
const int Time=86400;
const int X=131;
const int inf=0x3f3f3f3f;
const double PI = 1e-4;
double pai = 3.14159265358979323846; 
priority_queue<int,vector<int>,less<int>> q;int k,l; 
string n;
char s[MAX];int change1(int n,string x,int m){
    int sum = 0;int p = 0;for(int i = x.size() - 1 ; i >= 0 ; i-- ){
    if(isdigit(x[i])) sum+=(x[i] - '0') *pow(n,p) , p++; else  sum+=(x[i] - 55 ) *pow(n,p) , p++; }return sum;}
void change2(int n,int x,int m){
    int t = 0;if(x == 0) {
    cout<<0<<"\n";return;} while(x){
    int r = x % m;if(x >= 0 && r <= 9) s[t++] = r + '0';else s[t++] = r+ 55;x /= m;}for(int i = t - 1 ; i >= 0 ; i --)cout<<s[i];cout<<"\n";
}
signed main(){
      std::ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);while(cin >> k >> n >> l){
    int x = change1(k,n,10);//cout<<x<<endl;change2(10,x,l);}return 0;
}

问题 L: 统计成绩

题目描述
张琪曼指导了10个魔法学徒,每个学徒的数据包括学号、姓名、三门课的成绩,从键盘输入10个学生的数据,要求打印出三门课总平均成绩,以及最高分的学生数据(包括学号、姓名、三门课成绩、平均分数)。
输入
标准输入,共10行数据,分别为每个学徒的学号(整型),姓名(不超过8个字符)和三门课的成绩,以空格间隔。
输出
标准输出,第一行为三门课总平均成绩,第二行为总平均成绩最高分(保证没有并列的最高成绩)的学徒数据(包括学号、姓名、平均分数)以空格间隔,输出的浮点数小数点后保留两位,不考虑四舍五入。
样例输入 Copy
1 A 100 100 100
2 B 80 80 80
3 C 80 80 80
4 D 80 80 80
5 E 80 80 80
6 F 80 80 80
7 G 80 80 80
8 H 80 80 80
9 I 80 80 70
10 J 80 80 80
样例输出 Copy
81.67
1 A 100.00

这不是很简单的结构体操作吗,为啥写不对
注意精度就行,只要上次听过课,我觉得直接看代码能懂(狗头

#pragma GCC optimize(1)
#pragma GCC optimize(2)
#pragma GCC optimize(3,"Ofast","inline")
# include<iostream>
# include<iomanip>
# include<algorithm>
# include<cmath>
# include<cstdio>
# include<set>
# include<stack>
# include<queue> 
# include<map>
# include<string>
# include<cstring> # define eps 1e-9
# define fi first
# define se second
# define ll long long
# define int ll
// cout<<fixed<<setprecision(n) 
using namespace std;typedef unsigned long long ull;
typedef pair<int,int > PII; 
const int mod=1e9+7;
const int MAX=3e5+10;
const int Time=86400;
const int X=131;
const int inf=0x3f3f3f3f;
const double PI = 1e-4;
double pai = 3.14159265358979323846; 
priority_queue<int,vector<int>,less<int>> q;struct Node{
    int id;string name;int aa;int bb;int cc;int sum;
}a[15];
bool cmp(Node a,Node b){
    return a.sum > b.sum ;
}
double ans;signed main(){
      std::ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);for(int i = 0 ; i < 10 ; i ++ )cin >> a[i].id >> a[i].name >> a[i].aa >> a[i].bb >> a[i].cc,a[i].sum = a[i].aa + a[i].bb + a[i].cc ,ans+=a[i].sum ;sort(a,a+10,cmp);cout<<fixed<<setprecision(2)<<ans * 1.0 / 30<<"\n";cout<<a[0].id << " "<< a[0].name <<" "<< fixed<<setprecision(2)<<a[0].sum * 1.0 / 3;return 0;
}

问题 M: 生日

题目描述
李旭琳想统计每个学徒的生日,并按照从大到小的顺序排序。但她没有时间,所以请你帮她排序。
输入
第1行为学徒总人数n,随后n行分别是每人的姓名、出生年、月、日。
输出
有n行,即n个生日从大到小同学的姓名。(如果有两个同学生日相同,输入靠后的同学先输出)
样例输入 Copy
3
Yangchu 1992 4 23
Qiujingya 1993 10 13
Luowen 1991 8 1
样例输出 Copy
Luowen
Yangchu
Qiujingya

普普通通写个排序,然后就能过了(狗头

#include<stdio.h>
#include<iostream>
#include<cmath>
#include<cstring>
#include<ctype.h>
#include<algorithm>
using namespace std;
struct student 
{
    string s;int year,month,day;int q;
}s[100001];
bool cmp(struct student p,struct student q)
{
       if(p.year==q.year&&p.month==q.month&&p.day==q.day)return p.q>q.q;elseif(p.year==q.year&&p.month==q.month)return p.day<q.day;elseif(p.year==q.year)return p.month<q.month;elsereturn p.year<q.year;}
int main()
{
    int n,i;cin>>n;for(i=0;i<n;i++){
    cin>>s[i].s>>s[i].year>>s[i].month>>s[i].day;s[i].q=i;}sort(s,s+n,cmp);for(int i=0;i<n;i++)cout<<s[i].s<<endl;
}