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;
}
京公网安备 11010502036488号