Educational Codeforces Round 29
A. Quasi-palindrome
题目链接:http://codeforces.com/contest/863/problem/A
题目意思:问一个数可不可以在不上一些前缀0以后变成一个回文数。
题目思路:暴力减掉后缀0,然后把剩余的部分暴力看一下是不是回文,如果是回文说明yes,否则no
代码:
1 //Author: xiaowuga 2 #include <bits/stdc++.h> 3 using namespace std; 4 #define inf 0x3f3f3f3f 5 #define MAX INT_MAX 6 #define mem(s,ch) memset(s,ch,sizeof(s)) 7 const long long N=100000; 8 const long long mod=1e9+7; 9 typedef long long LL; 10 typedef int II; 11 typedef unsigned long long ull; 12 #define nc cout<<"nc"<<endl 13 #define endl "\n" 14 int main() { 15 ios::sync_with_stdio(false);cin.tie(0); 16 char s[20]; 17 cin>>s; 18 II len=strlen(s); 19 II r=len-1; 20 for(II i=len-1;i>=0;i--){ 21 if(s[i]=='0') r--; 22 else break; 23 } 24 for(II i=0,j=r;i<=j;i++,j--){ 25 if(s[i]!=s[j]){ 26 cout<<"NO"<<endl; 27 return 0; 28 } 29 } 30 cout<<"YES"<<endl; 31 return 0; 32 }
B. Kayaking
题目链接:http://codeforces.com/contest/863/problem/B
题目意思:现在有2n个人,n-1个可以装两个人的小皮艇,和两个只能装一个人的小皮艇,装两人的小船,如果两个人体重差太大,翻船值比较高,翻船值就是他们的绝对值,求最小的翻船值总和。
题目思路:我们考虑到n最大只有五十,所以我们可以暴力枚举挑出两个人去做一个人的小皮艇,然后剩下的人求翻船值,在这之前我们需要先排序。
代码:
1 /* *********************************************** 2 Author :xiaowuga 3 Created Time :2017年09月30日 星期六 22时39分17秒 4 File Name :Kayaking.cpp 5 ************************************************ */ 6 #include <bits/stdc++.h> 7 #define mem(s,ch) memset(s,ch,sizeof(s)) 8 typedef long long LL; 9 #define inf 0x3f3f3f3f 10 const long long N=1000000; 11 const long long mod=1e9+7; 12 using namespace std; 13 int main(){ 14 ios::sync_with_stdio(false);cin.tie(0); 15 int n; 16 int a[100]; 17 cin>>n; 18 n*=2; 19 for(int i=0;i<n;i++) cin>>a[i]; 20 sort(a,a+n); 21 int ans=inf; 22 for(int i=0;i<n-1;i++){ 23 for(int j=i+1;j<n;j++){ 24 int sum=0,t=-1; 25 for(int k=0;k<n;k++){ 26 if(k==i||k==j) continue; 27 sum+=a[k]*t; 28 t*=-1; 29 } 30 ans=min(ans,sum); 31 } 32 } 33 cout<<ans<<endl; 34 return 0; 35 }
C. 1-2-3
题目意思:现在有两个机器人做类似石头剪刀布的游戏,(1打败3,3打败2,2打败1)现在给出k,a,b,三个数以及两个3*3的矩阵我们设其中一个为A,另一个为B,k表示比赛k轮,a,b表示两个机器人第一场出的数,两个矩阵表示,加入上一场两个机器人出了a,b,那么这一场,两个机器人会分别出A[a][b]和B[a][b],问k轮以后各自赢了多少局。
题目思路:首先这个肯定是会存在循环节的,而且循环节不会太长,估计最多也就十几,我们可以先求出循环节长度,找到完整的循环节数量,每个循环节中两个机器人各自赢的数量,和开始进入完整循环节前那一小部分的胜负情况,以及剩余的不满一个完整循环节的胜负情况。然后加在一块就对了,唯一注意的就是很有可能k小于进入进入完整循环节的次数,需要特判一下。
题目链接:http://codeforces.com/contest/863/problem/C
代码:
1 /* *********************************************** 2 Author :xiaowuga 3 Created Time :2017年10月01日 星期日 01时32分10秒 4 File Name :C.1-2-3.cpp 5 ************************************************ */ 6 #include <bits/stdc++.h> 7 #define mem(s,ch) memset(s,ch,sizeof(s)) 8 typedef long long LL; 9 #define inf 0x3f3f3f3f 10 const long long N=1000000; 11 const long long mod=1e9+7; 12 using namespace std; 13 int A[4][4],B[4][4]; 14 int vis[4][4]={0}; 15 int ct[50][2]={0}; 16 int win[50]={0}; 17 int main(){ 18 ios::sync_with_stdio(false);cin.tie(0); 19 LL k; 20 int a,b; 21 cin>>k>>a>>b; 22 for(int i=1;i<=3;i++) for(int j=1;j<=3;j++) cin>>A[i][j]; 23 for(int i=1;i<=3;i++) for(int j=1;j<=3;j++) cin>>B[i][j]; 24 int c=0; 25 int ta=a,tb=b,x,y; 26 vector<pair<int,int> >q; 27 while(1){ 28 c++; 29 if(vis[ta][tb]) break; 30 vis[ta][tb]=c; 31 q.push_back(make_pair(ta,tb)); 32 x=ta;y=tb; 33 ta=A[x][y]; 34 tb=B[x][y]; 35 } 36 int cir=c-vis[ta][tb]; 37 int lim=vis[ta][tb]; 38 LL ansa=0,ansb=0; 39 if(k<lim){ 40 for(int i=0;i<k;i++){ 41 x=q[i].first;y=q[i].second; 42 if(x==y) continue; 43 else if((x==3&&y==2)||(x==2&&y==1)||(x==1&&y==3)) ansa++; 44 else ansb++; 45 } 46 cout<<ansa<<' '<<ansb<<endl; 47 return 0; 48 } 49 for(int i=0;i<lim-1;i++){ 50 x=q[i].first;y=q[i].second; 51 if(x==y) continue; 52 else if((x==3&&y==2)||(x==2&&y==1)||(x==1&&y==3)) ansa++; 53 else ansb++; 54 } 55 vector<pair<int,int> >p; 56 int cta=0,ctb=0; 57 for(int i=lim-1;i<q.size();i++){ 58 x=q[i].first;y=q[i].second; 59 p.push_back(make_pair(x,y)); 60 if(x==y) continue; 61 else if((x==3&&y==2)||(x==2&&y==1)||(x==1&&y==3)) cta++; 62 else ctb++; 63 } 64 LL t=(k-lim+1)/cir,l=(k-lim+1)%cir; 65 ansa+=t*cta;ansb+=t*ctb; 66 for(int i=0;i<l;i++){ 67 x=p[i].first;y=p[i].second; 68 if(x==y) continue; 69 else if((x==3&&y==2)||(x==2&&y==1)||(x==1&&y==3)) ansa++; 70 else ansb++; 71 } 72 cout<<ansa<<' '<<ansb<<endl; 73 return 0; 74 }
D. Yet Another Array Queries Problem
题目链接:http://codeforces.com/contest/863/problem/D
题目意思:现在给一个数列,包含n个数,然后将要进行q次操作,q次操作之后进行m次询问,每次询问给予一个下标询问进行q此操作以后该下标位置的值是多少?
操作有两种:
1.比如12345 ,1-3轮转,变成23145,每个数变成自己右边的数,右边界的数,变成左边界的数。
2.区间翻转
题目思路:我们观察到m的数量是比较少,我们我们考虑反向推倒,找出这个下标在q次操作之前的下标是多少,就可以直接在原数组里面查询了,所以最大mq的复杂度就可以解决问题,观察数据我们发现这个复杂度是可行的。
代码:
1 /* *********************************************** 2 Author :xiaowuga 3 Created Time :2017年10月02日 星期一 09时12分59秒 4 File Name :text.cpp 5 ************************************************ */ 6 #include <bits/stdc++.h> 7 #define mem(s,ch) memset(s,ch,sizeof(s)) 8 typedef long long LL; 9 #define inf 0x3f3f3f3f 10 #define second r 11 #define first l 12 const long long N=1000000; 13 const long long mod=1e9+7; 14 using namespace std; 15 struct node{ 16 int l,r,id; 17 bool operator <(const node &m) const{ 18 return l==r?r<m.r:l<m.l; 19 } 20 }tv[N]; 21 int main(){ 22 ios::sync_with_stdio(false);cin.tie(0); 23 int n; 24 cin>>n; 25 for(int i=1;i<=n;i++){ 26 cin>>tv[i].l>>tv[i].r; 27 tv[i].id=i; 28 } 29 sort(tv+1,tv+1+n); 30 for(int i=2;i<=n;i++){ 31 if(tv[i].r<=tv[i-1].r){ 32 cout<<tv[i].id<<endl; 33 return 0; 34 } 35 else if(tv[i].l<=tv[i-1].l){ 36 cout<<tv[i-1].id<<endl; 37 return 0; 38 } 39 tv[i].l=max(tv[i].l,tv[i-1].r+1); 40 } 41 cout<<-1<<endl; 42 return 0; 43 }