2017 CCPC秦皇岛站 铜银牌题总结

银牌题:

             

ZOJ 3981

A.  Balloon Robot

 

        题目大意:n个队伍围成 一个圈比赛,一个有m个队伍参加,给n个队伍的位置,和哪个队伍在第几分钟过题,现在有一个小机器人,每一分钟他移动一步转圈发气球,当他到达的队伍有过题就会给他一个气球,一个队伍会有一个不开心度,为得到气球和过题的时间差,机器人初始位置不确定,总不开心度最小为多少。

    题目思路:贪心。

           首先第一想法就是枚举每个位置分别计算,但是这样超时。  那么假如起始位置确定,可不可以计算出总贡献呢,答案是可以的。细细观察可以发现,每个过题的不开心度,一定小于m,当一个队过了题,机器人要么还没走到他,要么刚刚走过他,所以最差情况也就m-1,所以先选取位置1前一个作为起点,那么每个队伍的不开心度是可以确定下来的,就是看过这个题的时间现在机器人的位置和队伍位置的差值也就是(pos[i] - (b)%m + m )%m  。

           然后起始位置肯定选在这些过题队伍的位置,挨个枚举的话一定会出大问题,刚刚已经得到一个从0上一个开始的不开心度,按照不开心度排序,那么就是过题时间和队伍位置间隔的差值。当枚举到一个位置的时候,可以发现,前边的都比这个当前这个间隔小,后边的都比这个间隔大,所以统一缩小这个间隔的话,前边那群小的还要再补一个m。

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const ll MAXN = 1e5+5;
ll a[MAXN],pos[MAXN],ac,id;
int main()
{
    ll t;
    scanf("%lld",&t);
    while(t--){
        ll n,m,p;
        scanf("%lld%lld%lld",&n,&m,&p);
        for(ll i=1;i<=n;i++){
            scanf("%lld",&pos[i]);
            pos[i]--;
        }
        ll sum = 0;
        for(ll i=1;i<=p;i++){
            scanf("%lld%lld",&id,&ac);
            a[i] = (pos[id] - (ac)%m + m) %m;
            sum += a[i];
        }
        ll Max = sum;
        sort(a+1,a+1+p);
        for(ll i=1;i<=p;i++){
            ll now = sum - p*a[i] + (i-1)*m;
            Max = min(Max,now);
        }
        printf("%lld\n",Max);
    }
}

                 

 157 / 992GZOJ 3987Numbers

 

题目大意:给一个大整数,拆成m个数字相加,让这m个数字按位或最小,最小能是多小。

题目思路:很明显的贪心了,一开始想的先拆成二进制,然后从高位往后,一个1拆两个1,如果这一位不能再拆,就加上这一位的贡献,但是其实并没有这么麻烦,可以直接从高位往低位走一波,如果这一位的低位全1比n还大,那就没必要放这个1,相反就有必要放。

import java.util.*;
import java.math.*;
public class Main {
	public static BigInteger wei[] = new BigInteger[5005];
	public static void init()
	{
		wei[1] = BigInteger.valueOf(1);
		wei[0] = BigInteger.valueOf(0);
		for(int i=2;i<=5000;i++) {
			wei[i] = wei[i-1].multiply(BigInteger.valueOf(2));
		}
		for(int i=2;i<=5000;i++) {
			wei[i] = wei[i].add(wei[i-1]);
		}
	}
	public static void main(String [] arg) {
		init();
		Scanner cin = new Scanner(System.in);
		int T;
		T=cin.nextInt();
		while(T-->0) {
			BigInteger ans = BigInteger.valueOf(0);
			BigInteger a = cin.nextBigInteger();
			BigInteger b = cin.nextBigInteger();
			int Max = 0;
			for(int i=0;i<5000;i++) {
				if(wei[i].compareTo(a)>0) {
					Max = i;
					break;
				}
			}
			for(int i=Max ; i>=1;i--) {
				if(a.compareTo(wei[i-1].multiply(b))<=0)continue;
				BigInteger now = wei[i].subtract(wei[i-1]);
				ans = ans.add(now);
				BigInteger bei = a.divide(now);
				if(bei.compareTo(b)>0) {
					a=a.subtract(now.multiply(b) );
				}
				else {
					a=a.subtract(now.multiply(bei) );
				}
			}
			System.out.println(ans);
			
		}
	}
}

      铜牌题:

221 / 603EZOJ 3985

String of CCPC

 

题目思路:这个家伙最多放1个字母,因为我们可以发现,不管怎么插入字母最多只能有1的贡献,所以当没必要买第二个,那么这个题就转变成了能不能插入一个字母使得多1,也就几种情况判断一下。

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int MAXN = 2e5+5;
char C[MAXN];
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        int n;
        scanf("%d",&n);
        scanf("%s",C+1);
        int num = 0;
        for(int i=1;i<=n;i++){
            if(i+3<=n && C[i] == 'C' && C[i+1] == 'C' && C[i+2] == 'P' && C[i+3] == 'C'){
                num++;
            }
        }
        bool f=0;
        if(3<=n &&C[1] == 'C' && C[2] == 'P' && C[3] == 'C')f=1;
        if(n-2>=1 &&C[n] == 'P' && C[n-1] == 'C' && C[n-2] == 'C')f=1;
        for(int i=1;i<=n;i++){
            if(i+3<=n && C[i] == 'C' && C[i+1] == 'C' && C[i+2] == 'P' && C[i+3] == 'P')f=1;
            if(i+3<=n && C[i] == 'P' && C[i+1] == 'C' && C[i+2] == 'P' && C[i+3] == 'C')f=1;
            if(i+2<=n && C[i] == 'C' && C[i+1] == 'C' && C[i+2] == 'C'){
                if(i+4<=n && C[i+3]=='P' && C[i+4] == 'C'){
                }
                else f=1;
            }
        }
        if(f)printf("%d\n",num+1);
        else printf("%d\n",num);
    }
}
196 / 905MZOJ 3993Safest Buildings

 

这个就更水了,讲的是一个R的安全区,会缩小成一个半径为r的安全区,圆心不一定,问那么城市最安全,一个城市想要安全考虑圆心落在哪里就行了,一个城市画一个r的圈圈,和原点半径为R-r的画一个圈圈,交的部分就是圆心可选范围。排序

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int MAXN = 2e5+5;
struct node
{
    int x,y,id;
    double r;
    node(){r = 0;}
    node(int a,int b){
        x = a;y = b;
    }
}C[MAXN];
double dis(node a,node b)
{
    return sqrt( (a.x-b.x)*(a.x-b.x) + (a.y-b.y)*(a.y-b.y) );
}

double fun(node a, double r1, node b, double r2)
{
	double d = sqrt((a.x-b.x)*(a.x-b.x) + (a.y-b.y)*(a.y-b.y));
	if (d >= r1+r2)
		return 0;
	if (r1>r2)
	{
		double tmp = r1;
		r1 = r2;
		r2 = tmp;
	}
	if(r2 - r1 >= d)
		return M_PI*r1*r1;
	double ang1=acos((r1*r1+d*d-r2*r2)/(2*r1*d));
	double ang2=acos((r2*r2+d*d-r1*r1)/(2*r2*d));
	return ang1*r1*r1 + ang2*r2*r2 - r1*d*sin(ang1);
}
bool cmp(node a,node b)
{
    if(fabs(a.r - b.r) < 1e-8){
        return a.id<b.id;
    }
    return a.r>b.r;
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        int n,R,r;
        scanf("%d%d%d",&n,&R,&r);
        for(int i=1;i<=n;i++){
            C[i].id = i;
            scanf("%d%d",&C[i].x,&C[i].y);
            C[i].r= 0;
        }
        node now(0,0);
        for(int i=1;i<=n;i++){
            C[i].r = fun(C[i],r,now,R-r);
            //cout<<i<<" * "<<C[i].r<<" ++++ "<<endl;
        }
        sort(C+1,C+1+n,cmp);
        double Max = C[1].r;
        int cnt = 0;
        for(int i=1;i<=n;i++){
            if(fabs(C[i].r - Max) <1e-9 ){
                cnt++;
            }
            else break;
        }
        printf("%d\n",cnt);
        for(int i=1;i<=cnt;i++){
            if(fabs(C[i].r - Max) <1e-9 ){
                printf("%d%c",C[i].id,(i==cnt)?'\n':' ');
            }
            else break;
        }
    }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值