2017 ACM Jordanian Collegiate Programming Contest
A Chrome Tabs
题目链接
题意:1~n的开关,可以选择对于一个开关右边所有开关翻转,或者左边所有开关翻转。初始全为关,要求除第k个开关关着,其余全开的最小步数
思路:边界为1,中间为2,长度1特判
#include<cstdio> int T,n,k; int main(){ freopen("tabs.in","r",stdin); scanf("%d",&T); while(T--){ scanf("%d%d",&n,&k); if(n==1)puts("0"); else if(k==1||k==n)puts("1"); else puts("2"); } }
B OverCode
题目链接
思路:排序后贪心
#include<bits/stdc++.h> using namespace std; const int maxn = 1e5 + 5; int a[maxn]; int main() { freopen("overcode.in","r",stdin); int T; scanf("%d", &T); while (T--) { int n; scanf("%d", &n); for (int i = 1; i <= n; i++) { scanf("%d", &a[i]); } sort(a + 1, a + 1 + n); int cnt = 0; for (int i = 1; i <= n;) { int j = i + 5; if (j > n)break; if (a[j] - a[i] > 1000) { i++; } else { cnt++; i += 6; } } printf("%d\n", cnt); } }
C A message for you!
题目链接
题意:ABC..13个字符,每个字符付一个权值,求除给定字符串中字符之外剩余最大权值的字母
思路:排序,贪心
#include <bits/stdc++.h> using namespace std; char s[20]; int book[20]; struct node{ int f; int id; }nod[20]; bool cmp(node a,node b){ return a.f>b.f; } int main(){ freopen("scoreboard.in","r",stdin); int t; scanf("%d",&t); while(t--){ int k; memset(book,0,sizeof book); scanf("%d",&k); scanf("%s",s); for(int i=0;i<k;i++) book[s[i]-'A'+1]=1; for(int i=1;i<=13;i++){ scanf("%d",&nod[i].f); nod[i].id=i; } sort(nod+1,nod+14,cmp); for(int i=1;i<=13;i++){ if(book[nod[i].id]) continue; printf("%c\n",nod[i].id+'A'-1); break; } } }
D Test Cases
题目链接
题意:寻找存在多少个点对,满足对于区间 [l,r],其出现次数为奇数的值仅为一个。
思路:n^2暴力,以前缀记录奇数个数,开1e6的桶记录状态
#include <bits/stdc++.h> #define maxn 5005 using namespace std; int n; int a[maxn]; int vis[1000005]; void input(){ scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",&a[i]); } void solve(){ int ans=0; for(int i=1;i<=n;i++){ for(int j=i;j<=n;j++) vis[a[j]]=0; int odd=0; for(int j=i;j<=n;j++){ vis[a[j]]?odd--:odd++; vis[a[j]]^=1; if(odd==1) ans++; } } printf("%d\n",ans); } int main(){ freopen("cases.in","r",stdin); int t; scanf("%d",&t); while(t--){ input(); solve(); } }
E Robot I - Instruction Reduction
题目链接
题意:给出n*m的图,起始机器人位置、朝向以及机器人的行动步骤,R代表机器人顺时针转向,F val代表向当前方向走val步,当走到头就向右转继续走。
思路:记录每个方向最后走的真正方向,按照步骤模拟,压缩走的步数。
#include <bits/stdc++.h> #define maxn 505 using namespace std; int r,c,q; int sr,sc; char sdir; int dir; int tx[4]={0,1,0,-1}; int ty[4]={-1,0,1,0}; char g[maxn][maxn]; int f[maxn][maxn][5]; int a[(maxn<<1)*(maxn<<1)]; pair <int,int> pir[maxn<<1]; void input(){ scanf("%d%d%d",&r,&c,&q); scanf("%d%d %c",&sr,&sc,&sdir); if(sdir=='U') dir=0; else if(sdir=='R') dir=1; else if(sdir=='D') dir=2; else dir=3; for(int i=1;i<=r;i++){ scanf("%s",g[i]+1); } for(int i=2;i<r;i++){ for(int j=2;j<c;j++){ if(g[i][j]=='.'){ for(int d1=0;d1<4;d1++){ for(int d2=0;d2<4;d2++){ int dd=(d1+d2)%4; if(g[i+ty[dd]][j+tx[dd]]=='.'){ f[i][j][d1]=dd; break; } } } } } } int sty=sr;int stx=sc;int stdir=dir; int cnt=0; for(int i=1;i<=q;i++){ char flag; int step; scanf(" %c",&flag); if(flag=='R'){ dir=(dir+1)%4; }else{ scanf("%d",&step); while(step--){ dir=f[sr][sc][dir]; sr+=ty[dir]; sc+=tx[dir]; a[++cnt]=dir; } } } sr=sty;sc=stx;dir=stdir; int ans=0; for(int i=1;i<=cnt;i++){ for(int k=0;k<4;k++){ if(f[sr][sc][dir]==a[i]){ dir=a[i]; sr+=ty[dir]; sc+=tx[dir]; if(ans&&pir[ans].first==1){ ++pir[ans].second; }else pir[++ans]={1,1}; break; }else{ pir[++ans]={2,0}; dir=(dir+1)%4; } } } printf("%d\n",ans); } int main(){ freopen("reduce.in","r",stdin); int t; scanf("%d",&t); while(t--){ input(); // solve(); } }
G WiFi Password
题目链接
题意:对于给定的数组,求最长子序列满足或运算结果小于k
思路:位运算,递推
#include<iostream> #include<cstdio> #include<cstring> #include<map> #include<vector> #include<set> #include<queue> #include<algorithm> #include<string> #include<cmath> #include<stack> #include<functional> #include<bitset> #define ll long long #define maxn 100002 const int mod = 1e9 + 7; using namespace std; int num[maxn]; int value[22]; int t, n, v; bool check(){ int i, sum = 0; for(i = 0;i <= 18;i++){ if(value[i]){ sum += (1 << i); } } return sum <= v; } int main(void){ freopen("wifi.in","r",stdin); int i, j, l, ans; scanf("%d",&t); while(t--){ ans = 0; for(i = 0;i <= 18;i++){ value[i] = 0; } scanf("%d %d",&n,&v); for(i = 0;i < n;i++){ scanf("%d",&num[i]); } l = 0; for(i = 0;i < n;i++){ for(j = 0;j <= 18;j++){ if(num[i] & (1 << j)){ value[j]++; } } while(!check()&&l <= i){ for(j = 0;j <= 18;j++){ if(num[l] & (1 << j)){ value[j]--; } } l++; } ans = max(ans,i - l + 1); } printf("%d\n",ans); } return 0; }
M Winning Cells
题目链接
题意:一个n*n的格子,每个格子存在先后手,可以选择向上或向左走1~k任意步,求先手到(1,1)格的可行解格数
思路:找规律
#include<iostream> #include<cstdio> #include<cstring> #include<map> #include<vector> #include<set> #include<queue> #include<algorithm> #include<string> #include<cmath> #include<stack> #include<functional> #include<bitset> #define ll long long #define maxn 100002 const int mod = 1e9 + 7; using namespace std; int main(void){ freopen("chess.in","r",stdin); int t; ll n, k, ans; scanf("%d",&t); while(t--){ scanf("%I64d %I64d",&n,&k); if(n < (k + 1)){ ans = n * n - n; } else{ ans = n * n - (n / (k + 1)) * (n / (k + 1)) * (k + 1) - 2 * (n / (k + 1) * (n % (k + 1))) - n %(k + 1); } printf("%I64d\n",ans); } return 0; }