您的位置:首页 > 其它

2017 CCPC 秦皇岛

2017-11-15 18:30 295 查看
A:Balloon Robot

题意:有n个参赛人员,有m个座位围成一个圆,n个人员有固定的座位。比赛开始后,如果参赛人员在a时间做出一道题,气球在t时间送到,那么他就会有t-a的不高兴度。现在有一个送气球的机器人,每一个单位时间,它会顺时针移动一个位置,并送气球给相应位置的人,有p个做出问题,然后问它比赛开始的时候它的初始位置在哪,总不高兴度最少。

n,mandp(1<n≤105),(n≤m≤109),(1≤p≤105)

分析:开始的时候可以处理出一个从一个位置出发。然后暴力位置是肯定不行的,会T;

我们就处理从m出发。那么对于位置i,机器人到达位置i的时间是m*k+i,那么不开心度为(m*k+i-t)%m=(i-t)%i;对于任何一个起点j,不开心度为(i+j-t)%m

那么处理完之后可以得到每一个问题的不高兴度。把不高兴度从小到大排序。然后从后往前遍历,然后判读一下最小值就行了。

因为有些位置肯定是不行的。比如m = 10,happy[p]=8,那么如果位置加一,happy[1..p-1]都会加1,happy[p]也会加1,那么总的不开心度肯定是增加的。之后最后的happy[p]=0才有可能会减少。

#define mem(a,b) memset(a,b,sizeof(a))
#define ll long long
const int maxn = 1e5+10;
ll pos[maxn],h[maxn];
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
mem(pos,0);mem(h,0);
ll n,m,p;
scanf("%lld %lld %lld",&n,&m,&p);
for(int i=1;i<=n;i++) scanf("%lld",&pos[i]);
ll ans=0;
for(int i=0;i<p;i++)
{
ll x,t;
scanf("%lld %lld",&x,&t);
t=t%m;
h[i]=(pos[x]-t+m)%m;
ans+=h[i];
}
sort(h,h+p);
ll tt=0,total=ans;
for(int i=p-1;i>=0;i--)
{
int g=i,num=0;
while(h[g]==h[i]&&g>=0) {g--;num++;}
int k=m-h[i];
ll tmp = k*(p-num);
tmp=ans+tmp-h[i]*num-tt;
total=min(tmp,total);
tt+=m*num;
i=g+1;
}
printf("%lld\n",total);
}
}


C:Crusaders Quest

这个题很像简化版的zuma。直接放代码

using namespace std;
#define ll long long
#define mem(a,b) memset(a,b,sizeof(a))
const int maxn = 20;
char s[maxn];
int dp[maxn][maxn];
struct node
{
int num;
char c;
}a[15];
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
mem(dp,0);mem(a,0);
scanf("%s",s);
a[1].c=s[0];a[1].num=1;
int now=1,ans=0;
for(int i=1;i<9;i++)
{
if(s[i]==a[now].c)
{
a[now].num++;
}
else {
a[++now].c=s[i];
a[now].num=1;
}
}
for(int len=1;len<=now;len++)
{
for(int i=1;i+len-1<=now;i++)
{
int j=i+len-1;
if(i==j) {if(a[i].num==3) dp[i][j]=1;continue;}
if(a[i].c==a[j].c)
{
if(a[i].num+a[j].num==3)
dp[i][j]=max(dp[i][j],dp[i+1][j-1]+1);
else {
for(int k=i+2;k+1<j;k++){
if(a[k].c==a[i].c)
dp[i][j]=max(dp[i][j],dp[i+1][k-1]+dp[k+1][j-1]+1);
}
}
}
for(int k=i;k<j;k++)
dp[i][j]=max(dp[i][j],dp[i][k]+dp[k+1][j]);
}
}
printf("%d\n",dp[1][now]);
}
return 0;
}


E:String of CCPC

题意:有一个字符串,里面只有C,P两种字符,如果出现了一个CCPC,就算一个贡献,然后可以插入一个C或者P,问价值最大为多少

分析:插入的话只用判断CCP,CCC,CPC这三种情况就行了。同时还要注意不能破坏之前已经存在的CCPC

using namespace std;
const int maxn = 2e5+10;
char s[maxn];
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
int n;
scanf("%d",&n);
scanf("%s",s);
int flag=0,ans=0;
for(int i=0;i<n;i++)
{
if(s[i]=='C'&&i+3<n)
{
if(s[i+1]=='C'&&s[i+2]=='P'&&s[i+3]=='C'){
ans++;
continue;
}
}
if(s[i]=='C'&&i+2<n&&!flag)
{
if(s[i+1]=='P'&&s[i+2]=='C')
{
if(i>0&&s[i-1]=='C') continue;
flag=1;
ans++;
}
else if(s[i+1]=='C'&&s[i+2]=='P')
{
if(i+3<n&&s[i+3]=='C') continue;
flag=1;
ans++;
}
else if(s[i+1]=='C'&&s[i+2]=='C')
{
if(i+4<n&&s[i+3]=='P'&&s[i+4]=='C')
continue;
else {
flag=1;
ans++;
}
}
}
}
printf("%d\n",ans);
}
return 0;
}


G:Numbers

题意:一个数n,然后把它分成m个数,a1,a2,a3…am,∑<
cf8a
span style="display: inline-block; width: 0px; height: 2.776em;">m1ai=n

问a1ORa2ORa3ORa4…ORam最小值是多少。

分析:二进制分析,从高位往低位上看,看那一位上能不能一定是1.

然后数比较大,用java大数

import java.math.BigInteger;
import java.util.Scanner;

public class Main{
static BigInteger[] pre = new BigInteger[5005];
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int t;
BigInteger n,m,x,sum,k,y;

pre[0] = new BigInteger("1");
x = new BigInteger("2");
y = new BigInteger("0");
for(int i=1;i<5005;i++)
pre[i]=pre[i-1].multiply(x);
t = in.nextInt();
for(int ca=0;ca<t;ca++)
{
n = in.nextBigInteger();
m = in.nextBigInteger();
sum = n;
BigInteger ans = y;
k = n.divide(m);
if(n.compareTo(k.multiply(m))==0) {
System.out.println(k);
continue;
}
BigInteger temp = n;
int tol = 0;
//System.out.println(temp);
while(temp.compareTo(y)>0)
{
temp = temp.divide(x);tol++;
}
while(sum.compareTo(y)>0)
{
if(sum.compareTo(m)<=0) {
ans = ans.add(pre[0]);
break;
}
for(;tol>=0;tol--)
{
if(sum.compareTo(m.multiply(pre[tol-1]))>0)
{
if(sum.compareTo(m.multiply(pre[tol]).subtract(m))<=0) {
tol = tol - 1;
sum = sum.subtract(m.multiply(pre[tol]));
}
else {
BigInteger tt = sum.divide(pre[tol]);
sum = sum.subtract(tt.multiply(pre[tol]));
}
break;
}
}
ans = ans.add(pre[tol]);
}
System.out.println(ans);
}

}

}


L:One-Dimensional Maze

分析:签到题,左右跑一下就行了

M:Safest Buildings

题意:二维平面,开始有一个以原点为圆心的半径为R的安全圆,然后,会在这个安全圆从随机出现半径为r的次安全圆(次安全圆完全包含在安全圆中),如果在次安全圆中,则安全。然后给你一些建筑物的坐标,问这些建筑物中安全概率最大的是哪些

分析:

如果r很大的时候

2*r>=R 那么以原点为圆心,半径为(2*r-R)的圆内,概率都是1

如果r很小的时候

2*r

using namespace std;
#define mem(a,b) memset(a,b,sizeof(a))
const int maxn = 100+10;
struct node
{
int id;
int t;
}a[maxn];
bool cmp(node a1,node a2)
{
return a1.t<a2.t;
}
bool cmp2(node a1,node a2)
{
return a1.id<a2.id;
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
mem(a,0);
int n,R,r;
scanf("%d %d %d",&n,&R,&r);
for(int i=1;i<=n;i++){
int x,y;
scanf("%d %d",&x,&y);
a[i].t=x*x+y*y;a[i].id=i;
}
sort(a+1,a+n+1,cmp);
int lim = R*R;
if(a[1].t>lim)
{
printf("0\n\n");continue;
}
int ansr = 0;
if(2*r>=R) ansr = 2*r-R;
else ansr = R-2*r;
int temp = ansr*ansr;
int i=1;
for(;i<=n;i++)
{
if(a[i].t>temp) break;
}
if(i-1>0){
printf("%d\n",i-1);
sort(a+1,a+i,cmp2);
for(int j=1;j<=i-1;j++)
{
if(j>1) printf(" ");
printf("%d",a[j].id);
}
printf("\n"); continue;
}
int k=2;
for(;k<=n;k++)
{
if(a[k].t>a[1].t)
break;
}
printf("%d\n",k-1);sort(a+1,a+k,cmp2);
for(int j=1;j<=k-1;j++)
{
if(j>1) printf(" ");
printf("%d",a[j].id);
}
printf("\n");
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: