Codeforces Round #280 (Div. 2) 解题报告(A B C D E)

A. Vanya and Cubes


        思路:累加计算叠到每个高度至少需要多少方块,然后找最后一个满足的即可。

#include<iostream>
#include<queue>
#include<map>
#include<set>
#include<vector>
#include<algorithm>
#include<string.h>
#include<cstdio>

using namespace std;

#define ll long long
#define INF 1000000000

int main(){
	int n;
	while(cin>>n){
		int i;
		int sum=0;
		int ssum=0;
		for(i=1;;i++){
			sum+=i;
			ssum+=sum;
			if(ssum>n)break;
		}
		cout<<i-1<<endl;
	}
	return 0;
}

B. Vanya and Lanterns


        思路:想都没想敲了个二分。。结果T了。。正解是先排序,然后算相邻两个灯距离/2和首尾灯到边界的最大值,直接输出最大值即可。


#include<iostream>
#include<queue>
#include<map>
#include<set>
#include<vector>
#include<algorithm>
#include<string.h>
#include<cstdio>

using namespace std;

#define ll long long
#define INF 1000000000

double pos[1010];

int n;
double l;

int main(){
	while(cin>>n>>l){
		for(int i=0;i<n;i++){
			cin>>pos[i];
		}
		sort(pos,pos+n);
		
		double re=0;
		for(int i=0;i<n;i++){
			re=max(re,(pos[i+1]-pos[i])/2);
		}
		re=max(re,pos[0]);
		re=max(re,l-pos[n-1]);	
		printf("%.10lf\n",re);
	}
	return 0;
}

C. Vanya and Exams

        思路:贪心。优先写性价比最高的,注意不要溢出分数上限就行了。


#include<iostream>
#include<queue>
#include<map>
#include<set>
#include<vector>
#include<algorithm>
#include<string.h>
#include<cstdio>

using namespace std;

#define ll long long
#define INF 1000000000

struct ex{
	int a;
	int b;
};
ex exs[100010];

bool cmp(ex a,ex b){
	return a.b<b.b;
}

ll n,r,avg;

int main(){
	while(cin>>n>>r>>avg){
		ll sum=0;
		for(int i=1;i<=n;i++){
			scanf("%d%d",&exs[i].a,&exs[i].b);
			sum+=exs[i].a;
		}
		sort(exs+1,exs+1+n,cmp);
		ll need=avg*n-sum;
		
		if(need<=0){
			cout<<0<<endl;
			continue;
		}
		
		ll ans=0;
		for(int i=1;i<=n;i++){
			ll tmp=need;
			need-=min(need,r-exs[i].a);
			ans+=(tmp-need)*exs[i].b;
			if(need==0)break;
		}
		cout<<ans<<endl;
	}
	return 0;
}


D. Vanya and Computer Game


        思路:居然是判断谁补的刀。。先是算出了一个差不多打死的时刻,然后去模拟。。结果超时了。应该这样做,把两个人的攻击间隔改为y秒A一刀和x秒A一刀,攻击频率没有改变,整型好处理。。然后把他们同时A出第一刀的时刻(其实就是最小公倍数)前的所有攻击和是谁A的都按时间顺序存在数组里。这样他们同时出刀以后,出刀顺序还是那个序列。最后把血量取模,检查最后一刀是谁A的就行。

        关于"Both"的判断,有两种情况,一是最后剩2滴血;同时出刀,二是最后剩一滴血,同时出刀。只要检查A死那刀的前后各一刀即可判断出来。


#include<iostream>
#include<cmath>
#include<queue>
#include<map>
#include<set>
#include<vector>
#include<algorithm>
#include<string.h>
#include<cstdio>

using namespace std;

#define ll long long
#define INF 1000000000

ll gcd(ll a,ll b){
	return a%b==0?b:gcd(b,a%b);
}

pair<ll,bool> p[2000000];

int main(){
	ll n,x,y;
	while(cin>>n>>x>>y){
		ll lcm=x*y/gcd(x,y);
			
		int cnt=0;
		for(ll i=x;i<=lcm;i+=x){
			p[cnt].second=0;
			p[cnt++].first=i;
		}
		for(ll i=y;i<=lcm;i+=y){
			p[cnt].second=1;
			p[cnt++].first=i;
		}
		sort(p,p+cnt);
		
		for(int i=1;i<=n;i++){
			ll a;
			scanf("%I64d",&a);
			
			a--;
			a-=a/(x+y)*(x+y);
			a%=cnt;
			if(p[a].first==p[(a+1)%cnt].first&&p[a].second!=p[(a+1)%cnt].second){
				printf("Both\n");
				continue;
			}
			if(p[a].first==p[(a+cnt-1)%cnt].first&&p[a].second!=p[(a+cnt-1)%cnt].second){
				printf("Both\n");
				continue;
			}
			
			if(p[a].second==1){
				printf("Vanya\n");
			}else{
				printf("Vova\n");
			}
		}
	}
	return 0;
}

E. Vanya and Field


        思路:gcd(dx,n)=1和gcd(dy,n)=1告诉我们,按这个向量,可以循环取n个点。然后把所有的点分为n类就行了,具体是x=0,y=i时循环能取到的点,分到i类,i取0~n-1。我的分类方法是,求dx关于模n的逆元(其实总复杂度没有减小,暴力就可以),然后据此算出x增加1时,y的增量。然后打表算出第0类(x=0,y=0能循环到的点)在x取不同值时,y的取值,据此就可以给所有点分类了。最后就是统计哪类点最多,随便找一个该类的点输出即可。


#include<iostream>
#include<cmath>
#include<queue>
#include<map>
#include<set>
#include<vector>
#include<algorithm>
#include<string.h>
#include<cstdio>

using namespace std;

#define ll long long
#define INF 1000000000

int cnt[1000010];
int x[100010];
int y[100010];

int ExtendedEuclid(int f, int d, int *result) {
    int x1, x2, x3, y1, y2, y3, t1, t2, t3, q;
    x1 = y2 = 1;
    x2 = y1 = 0;
    x3 = (f >= d) ? f : d;
    y3 = (f >= d) ? d : f;
    while (1) {
        if (y3 == 0) {
            *result = x3;
            return 0;
        }
        if (y3 == 1) {
            *result = y2; 
            return 1;
        }
        q = x3 / y3;
        t1 = x1 - q*y1;
        t2 = x2 - q*y2;
        t3 = x3 - q*y3;
        x1 = y1;
        x2 = y2;
        x3 = y3;
        y1 = t1;
        y2 = t2;
        y3 = t3;
    }
}

int tab[1000010];

int main(){
	int n,m,dx,dy;
	while(cin>>n>>m>>dx>>dy){
		memset(cnt,0,sizeof(cnt));
		int _x;//x的逆元 
		ExtendedEuclid(dx,n,&_x);
		_x+=n; _x%=n;
		int _dy=((ll)dy*_x)%n;//x增加1时,y的增量 

		for(int i=1;i<n;i++){
			tab[i]=tab[i-1]+_dy;
			tab[i]%=n;
		}
		
		for(int i=1;i<=m;i++){
			scanf("%d%d",&x[i],&y[i]);
			cnt[(y[i]+n-tab[x[i]])%n]++;
		}
		
		int k=0;
		int MAX=0;
		for(int i=0;i<n;i++){
			if(cnt[i]>MAX){
				MAX=cnt[i];
				k=i;
			}
		}
		
		int ans;
		for(int i=1;i<=m;i++){
			
			if((y[i]+n-tab[x[i]])%n==k){
				ans=i;
				break;
			}
		}
		cout<<x[ans]<<" "<<y[ans]<<endl;
	}
	return 0;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值