A题目链接:http://codeforces.com/problemset/problem/792/A
//
题意: 给你n个数,问你两个数直接的差值得绝对值最小为多少,及有多少对满足这样的数/
分析:
排序后直接扫一遍即可
//
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
const int maxn = 200010;
int a[maxn];
int main()
{
int n;
scanf("%d",&n);
for(int i=0;i<n;i++)
scanf("%d",&a[i]);
sort(a,a+n);
int mindis = 2000000010;
int pairs = 0;
for(int i=0;i<n-1;i++)
{
int t = abs(a[i+1]-a[i]);
if(t < mindis)
{
mindis = t;
pairs = 1;
}
else if(t == mindis) pairs++;
}
printf("%d %d\n",mindis,pairs);
return 0;
}
B题目链接:http://codeforces.com/problemset/problem/792/B
//
题意: 有n个人顺时针围成一圈,编号从1~n,刚开始时第一个人为leader,现在进行k轮游戏
每一轮有一个数ai,表示从leader的后一个人开始往后数ai个人,将最后一个人出圈,并且将出圈人的后一个人设为下一轮的leader
问你每一轮出圈人的编号?
分析:
由于n很小,所以我们可以直接进行模拟即可,将圈直接看成一行,编号1~n
在每一轮中有:
leader :标记leader为从头开始的第几个人
n: 还剩下的人数
所以下一个出圈的人为第 (leader + a[i]) % n 个人
再将后面的编号往前移动一位即可
依次模拟下去
**注意对边界情况的处理**
//
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
const int maxn = 110;
int ch[maxn];
int a[maxn];
int ans[maxn];
int main()
{
int n,k;
scanf("%d %d",&n,&k);
for(int i=1;i<=n;i++) ch[i] = i;
for(int i=1;i<=k;i++) scanf("%d",&a[i]);
int leader = 1;
for(int i=1;i<=k;i++)
{
int t = (leader + a[i]) % n;
if(t == 0) t = n;
ans[i] = ch[t];
for(int j = t+1;j<=n;j++) ch[j-1] = ch[j];
if(t == n) leader = 1;
else leader = t;
n--;
}
for(int i=1;i<=k;i++)
{
if(i == 1) printf("%d",ans[i]);
else printf(" %d",ans[i]);
}
printf("\n");
return 0;
}
C题目链接:http://codeforces.com/problemset/problem/792/C
//
**代码是WA的,今后找机会改**
题意: 给你一个长度最大为100000的正整数,为你最少删去多少个数使得他是3的倍数(没有前导0)
分析:一个数的所有位数之和是3的倍数那么那个数就是3的倍数
我们也可以将每一位看成0,1,2,3
所以这个数 %3 后只有可能有3中情况:0,1,2、
若余数为0:可以直接输出
若余数为1:去掉一个1或两个2 (有很多关于0的情况的讨论)
若余数为2:去掉一个2或两个1
分情况讨论即可
//
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
const int maxn = 100010;
char s[maxn];
int main()
{
freopen("input.txt","r",stdin);
while(scanf("%s",s)!=EOF)
{
int len = strlen(s);
int sum = 0;
int num0 = 0;
int num1 = 0;
int num2 = 0;
for(int i=0;i<len;i++)
{
sum += s[i] - '0';
if(s[i]-'0' == 0) num0++;
else if((s[i]-'0') % 3 == 1) num1++;
else if((s[i]-'0') % 3 == 2) num2++;
}
int t = sum % 3;
if(t == 0) printf("%s\n",s);
else if(t == 1)
{
if(num1 == 0)
{
if(num2 <2) printf("-1\n");
else if(num2 ==2)
{
if(len == 2) printf("-1\n");
else
{
int k = 0;
while(s[k] == '0' || (s[k]-'0')%3 == 2) k++;
if(k >= len) printf("0\n");
else
{
for(int i=k;i<len;i++) if((s[i]-'0')%3 != 2)
printf("%c",s[i]);
printf("\n");
}
}
}
}
else if(num1 > 1)
{
printf("%c",s[0]);
int num = 1;
for(int i=1;i<len;i++)
{
if(num == 1 && (s[i]-'0') == 1) num--;
else printf("%c",s[i]);
}
printf("\n");
}
else if(num1 == 1)
{
if((s[0]-'0')%3 != 1)
{
printf("%c",s[0]);
int num = 1;
for(int i=1;i<len;i++)
{
if(num == 1 && (s[i]-'0')%3 == 1) num--;
else printf("%c",s[i]);
}
printf("\n");
}
else
{
if(num2 < 2)
{
int k=1;
while(s[k]=='0') k++;
if(k >= len) k = len-1;
for(int i=k;i<len;i++) printf("%c",s[i]);
printf("\n");
}
else
{
if(s[1]!='0')
{
for(int i=1;i<len;i++) printf("%c",s[i]);
printf("\n");
}
else if(s[2] != '0')
{
for(int i=2;i<len;i++) printf("%c",s[i]);
printf("\n");
}
else
{
int num = 2;
printf("%c%c%c",s[0],s[1],s[2]);
for(int i=3;i<len;i++)
{
if(num > 0 && (s[i]-'0')%3 == 2) num--;
else printf("%c",s[i]);
}
printf("\n");
}
}
}
}
}
else if(t == 2)
{
if(num2 == 0)
{
if(num1 <2) printf("-1\n");
else if(num1 ==2)
{
if(len == 2) printf("-1\n");
else
{
int k = 0;
while(s[k] == '0' || (s[k]-'0')%3 == 1) k++;
if(k >= len) printf("0\n");
else
{
for(int i=k;i<len;i++) if((s[i]-'0')%3 != 1)
printf("%c",s[i]);
printf("\n");
}
}
}
}
if(num2 > 1)
{
printf("%c",s[0]);
int num = 1;
for(int i=1;i<len;i++)
{
if(num == 1 && (s[i]-'0')%3 == 2) num--;
else printf("%c",s[i]);
}
printf("\n");
}
if(num2 == 1)
{
if((s[0]-'0')%3 != 2)
{
printf("%c",s[0]);
int num = 1;
for(int i=1;i<len;i++)
{
if(num == 1 && (s[i]-'0')%3 == 2) num--;
else printf("%c",s[i]);
}
printf("\n");
}
else
{
if(num1 < 2)
{
int k=1;
while(s[k]=='0') k++;
if(k >= len) k = len-1;
for(int i=k;i<len;i++) printf("%c",s[i]);
printf("\n");
}
else
{
if(s[1]!='0')
{
for(int i=1;i<len;i++) printf("%c",s[i]);
printf("\n");
}
else if(s[2] != '0')
{
for(int i=2;i<len;i++) printf("%c",s[i]);
printf("\n");
}
else
{
int num = 2;
printf("%c%c%c",s[0],s[1],s[2]);
for(int i=3;i<len;i++)
{
if(num > 0 && (s[i]-'0')%3 == 1) num--;
else printf("%c",s[i]);
}
printf("\n");
}
}
}
}
}
}
return 0;
}
D题目链接:http://codeforces.com/problemset/problem/792/D
//
题意:给你一颗完全二叉树,标号规则如图所示(先序序列),
现在从一个节点出发,可以进行U:向上,R:向右,L:向左 移动这三种操作 (当不能移动时不动)
经过s操作后,问你最后到达哪一节点?
分析:
满二叉树的标号方式和我们所学的树状数组一样,所以我们想到了树状数组
设当前所在节点的编号为u,那么pos = u&-u : 表示和u处在层的第一个节点的编号
若 u&(2*pos) != 0 表示 u 节点在父节点的右侧
若 u&(2*pos) == 0 表示 u 节点在父节点的左侧
并且我们发现从最后一层开始相邻两层之间的节点的编号差值从1 开始成倍增长
所以我们根据以上信息模拟即可
//
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
long long n,q,u,root;
string s;
int main()
{
scanf("%I64d %I64d",&n,&q);
root = (n + 1) / 2;
for(int i=0;i<q;i++)
{
cin>>u>>s;
int len = s.length();
for(int j=0;j<len;j++)
{
long long pos = u&-u;
if(s[j] == 'U' && u != root)
{
if(u&(2*pos)) u -= pos;
else u += pos;
}
else if(s[j] == 'L')
{
pos /= 2;
u -= pos;
}
else if(s[j] == 'R')
{
pos /= 2;
u += pos;
}
}
printf("%I64d\n",u);
}
return 0;
}