A Alice and Bob(不是很理解)
思路:我们可以对n进行质因数分解,那么其实就是把n分成了一些石子,对于每个素因数p都看作一堆石子,那么每次操作转化为从某堆石子拿走一些石子,那么就转化为Anti−Nim博弈
根据Anti−Nim游戏结论,当且仅当所有堆石子数等于1并且所有堆石子数量异或和为0(有偶数堆)或者存在一堆石子数大于1并且所有堆石子数量异或和大于0先手必胜;反之必败。所以先分解质因数,然后使用Anti−Nim博弈
#include<iostream>
#define int long long
using namespace std;
signed main(){
int n,ans=0;
bool f=0;
cin>>n;
for(int i=2;i*i<=n;i++){
int ant=0;
while(n%i==0){
n/=i;
ant++;
}
if(ant>1){
f=1;
}
ans^=ant;
}
if(n>1){
ans^=1;
}
if((!f&&!ans)||(f&&ans)){
cout<<"Alice win";
}else{
cout<<"Bob win";
}
return 0;
}
关于异或:C语言异或操作详解
B 打对子
思路:分别判断每一个字母数量的奇偶性,若为奇数,则该牌打对子将无法打完使用“s-'A'的形式”,将字母转化为数字,再使用数组计算字母的数目
新方法:for(char i='A';i<='Z';i++)
赛场AC代码:
#include<cstdio>
#include<iostream>
#include<set>
#define int long long
using namespace std;
int a[30],b[30];
signed main(){
int n,ans1=0,ans2=0;
cin>>n;
string s1;
string s2;
cin>>s1;
cin>>s2;
for(int i=0;i<n;i++){
int num=s1[i]-'A';
if(a[num]==0){
ans1++;
a[num]++;
}else{
ans1--;
a[num]=0;
}
num=s2[i]-'A';
if(b[num]==0){
ans2++;
b[num]++;
}else{
ans2--;
b[num]=0;
}
}
cout<<ans1<<endl;
if(ans1<ans2){
cout<<"YES";
}else{
cout<<"NO";
}
return 0;
}
标准答案:
#include<bits/stdc++.h>
using namespace std;
int n, ca, cb, sa[30], sb[30];
string a, b;
int main(){
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
cin >> n >> a >> b;
for (int i = 0; i < n; i++)
{
sa[a[i] - 'A']++;
sb[b[i] - 'A']++;
}
for (int i = 0; i < 26; i++)
{
if (sa[i] % 2 == 1)
ca++;
if (sb[i] % 2 == 1)
cb++;
}
cout << ca << endl;
if (ca < cb) cout << "YES";
else cout << "NO";
return 0;
}
D 纪念品领取
思路:要考虑到多种情况。第一种,未被抽到的同学大于等于5人时,直接从前往后输出5位同学的编号即可。第二种,未被抽到的同学小于5人且每个同学最多只被抽中一次。第三种,未被抽到的同学小于5人且每个同学被抽中不止一次,而且还要考虑再次被抽中时是否对结果产生影响(也就是是否在前五个同学中抽取)
#include<cstdio>
#include<iostream>
#include<algorithm>
#define int long long
using namespace std;
const int N=100005;
int a[N],b[N];
bool vis[N],vis1[N],vis2[N];
signed main(){
int n,m;
cin>>n>>m;
for(int i=1;i<=m;i++){
cin>>a[i];
vis[a[i]]=1;
}
int ans=0;
for(int i=1;i<=n;i++){
if(!vis[i]){
b[++ans]=i;
}
if(ans==5){
break;
}
}
int s,s2=ans;
for(int i=1;i<=m;i++){
if(!vis1[a[i]]){
vis1[a[i]]=1;
ans++;
}
if(ans==5){
s=i;
break;
}
}
for(int i=s+1;i<=m;i++){
if(vis1[a[i]]){
vis2[a[i]]=1;
}
}
for(int i=1;i<=m;i++){
if(!vis2[a[i]]){
b[++s2]=a[i];
}
if(s2==5){
break;
}
}
sort(b+1,b+6);
for(int i=1;i<=5;i++){
cout<<b[i]<<' ';
}
return 0;
}
标准答案:
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <vector>
#define int long long
using namespace std ;
typedef pair<int,int>PII;
const int N=200005;
int n,m;
int a[N];
vector<int> v,ans;
bool st[N];
signed main(){
cin>>n>>m;
for(int i=1;i<=m;i++){
cin>>a[i];
}
for(int i=m;i>=1;i--){
if(st[a[i]]){
continue;
} //出现过
v.push_back(a[i]) ; //没有出现过
st[a[i]]=1; //标记被选过
}
//v记录了选中的人的排队倒序
for(int i=1;i<=n;i++){ // 答案从没被抽到的人中选
if(!st[i]&&ans.size()<5){
ans.push_back(i);
}
}
while(ans.size()<5){
ans.push_back(v.back()),v.pop_back() ; // 从抽到人中选中
}
sort(ans.begin(),ans.end()) ;
for(int i=0;i<5;i++){
cout<<ans[i]<<' ';
}
return 0 ;
}
一种思路,使用pair: D - 纪念品领取
重要!!!! 关于pair的使用:C++ pair的基本用法总结(整理)
F 买车
思路:定义结构体sta[i].a,sta[i].b,sta[i].c分别表示车店的距离,提供的车最远跑的公里数,最远跑到的距离,对车店的距离排序,遍历每个车店并记录最远跑到的距离,当当前的距离大于车站的距离时,更新当前的距离
#include<iostream>
#include<algorithm>
#define int long long
using namespace std;
const int N=100005;
struct Station{
int a;
int b;
int c;
}sta[N];
bool cmp(Station x,Station y){
return x.a<y.a;
}
signed main(){
int n,m,t,ans=0;
cin>>n>>m>>t;
for(int i=1;i<=m;i++){
cin>>sta[i].a>>sta[i].b;
sta[i].c=sta[i].a+sta[i].b;
}
sort(sta+1,sta+1+m,cmp);
int nmax=0,d=t;
for(int i=1;i<=m;i++){
if(sta[i].a>d){
d=nmax;
ans++;
nmax=0;
}
if(sta[i].c>nmax){
nmax=sta[i].c;
}
}
if(d>=n){
cout<<ans;
}else{
cout<<-1;
}
return 0;
}
K 糟糕的一天
思路:判断后面的值是否有大于当前的值,倒着进行处理即可,不断更新倒着的最大值
赛场AC代码:
#include<cstdio>
#include<iostream>
#define int long long
using namespace std;
const int N=1000005;
int a[N],b[N];
signed main(){
int n,ans=0;
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i];
}
b[n]=a[n];
for(int i=n-1;i>=1;i--){
b[i]=max(a[i],b[i+1]);
}
for(int i=1;i<=n;i++){
if(a[i]<b[i]){
ans++;
}
}
cout<<ans;
return 0;
}
标准答案(更简洁):
#include<iostream>
#include<algorithm>
using namespace std;
const int N=1000005;
int a[N];
int main(){
int n;
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i];
}
int ans=0,tag=a[n];
for(int i=n;i>=1;i--){ // 倒着进行处理即可
if(a[i]<tag){
ans++;
}
tag=max(tag,a[i]);
}
cout<<ans<<endl;
return 0;
}