Codeforces Round #711 (Div. 2)

A. GCD Sum

签到题 直接求就好了 没啥好说的

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxt=1000;
int t;
ll n;
bool isprime(ll x,ll y){//求最小公因数 
	if(x==1&&y==1) return true;
	int temp;
	while(true){
		temp=x%y;
		if(temp==0){
			break;
		}	
		else {
			x=y;
			y=temp;
		}
	}
	if(y==1) return true;
	else return false;
}

int main()
{
	cin>>t;
	while(t --){
		scanf("%lld",&n);	
		ll cnt;
		while(1){
			ll r=0;
			cnt=n;
			while(cnt){
				 r+=cnt%10;
				cnt /=10;
			}
			if(isprime(r,n)!=1) {
				cnt=n;
				break;	
			}
			else n++;
		}
	printf("%lld\n",cnt);
	}		
return 0;	
}

B. Box Fitting

优先队列 贪心
使用优先队列这道题就会变得十分简单
每次都枚举一个宽度为w的长度到优先队列里面 然后从大到小给所有的长方形进行排序 构造一个循环
每次将一个长方形的宽度与优先队列里的w作比较 如果小于这个w 则说明在这一层可以放下 并且剩余宽度为w减掉这个长方形的宽度 如果放不下 就要再输入一个w到优先队列里面 也就是高度会加一
你可以把优先队列里面的节点当作一的高度 有多少个节点 就说明 需要多高的高度

#include<iostream>
#include<algorithm>
#include<cstring>
#include<queue>
#include<vector>
using namespace std;
typedef long long ll;
const int maxt=1e5+10;
ll t,h[maxt];
bool cmp(ll a,ll b){
	return a>b;
}

int main()
{
	cin>>t;
	while(t --){	
		ll n,w;	
		scanf("%lld %lld",&n,&w);
		for(int i=0;i <n;i ++)
			scanf("%lld",&h[i]);
		sort(h,h+n,cmp);
		priority_queue<int> q;//优先队列
		for(int i=0;i <n;i ++){
			if(q.empty()){
				q.push(w);
			}
			if(q.top()<h[i]){
				q.push(w-h[i]);
			}
			else {
				int now=q.top();
				q.pop();
				q.push(now-h[i]);
			}		
		} 
		 
		cout<<q.size()<<endl;
	}
	
return 0;	
}
priority_queue<int> q 优先队列  其用法与队列完全相同
但是会给队列中的节点进行排序 默认是从大到小进行排序
队列中的节点是按照降序排序的 
如果想按照升序排序的话  可以写成
priority_queue<int,vector<int>,greater<int>> q;
如果存入的是字符串则会按照字典序排序

C. Planar Reflections

dp题 就是要注意几个细节
设h[i][j] 表示为这个粒子前面有i个平面 质量为j会产生多少个粒子;
每当它穿过一个平面的时候 就会产生一个粒子h[n-i][j-1] 也就是那个相反方向的副本粒子 它需要穿过 n - i 个平面 并且质量会减一
还会产生一个粒子h[i-1][j] 也就是平面数减一 质量不变的粒子
当质量为1的时候 总是产生一个粒子 h[i][1]=1;
当平面为0的时候 总是产生一个粒子 h[0][j]=1;
综上就可以得出 dp表达式
h[i][j]=(h[n-i][j-1],h[i-1][j]);

#include<iostream>
#include<algorithm>
#include<cstring>
#include<queue>
#include<vector>
using namespace std;
typedef long long ll;
const int maxt=1e3+10;
const ll mod=1e9+7;
int t,n,k;
ll h[maxt][maxt];
//h[i][j] 表示某个粒子前面有i层平面 质量为j
int main()
{
	cin>>t;
	while(t --){	
		scanf("%d %d",&n,&k);
		for(int i=0;i <=n;i ++) h[i][1]=1;
		for(int i=1;i <=k;i ++) h[0][i]=1;			
		
		for(int j=1;j <=k;j ++)//注意需要先枚举j质量 再枚举i平面
			for(int i=1;i <=n;i ++)		
				h[i][j]=(h[n-i][j-1]+h[i-1][j])%mod;
		/*for(int i=1;i <=n;i ++)		
			for(int j=1;j <=k;j ++)
				h[i][j]=(h[n-i][j-1]+h[i-1][j])%mod;*/	
				
		/*for(int i=1;i <=n;i ++){
			for(int j=1;j <=k;j ++){
				cout<<h[i][j]<<" ";	
			}
			cout<<endl;
		} */
			
		cout<<h[n][k]<<endl;				
	}
	
return 0;	
}

在这道题目里面为什么要先枚举j质量 再枚举i平面呢?
谁先开始不都是一样的吗 都是枚举那么多次。

其实不然 因为我们这个dp表达式为h[i][j]=(h[n-i][j-1],h[i-1][j]);
当你要求h[3][3] 的值的时候 我们是从h[1][1]开始枚举的 如果我们先以i开始枚举的话 那下一个就是要求h[1][2] 当我们要求这个的时候 也就是 h[1][2]=(h[2][1],h[0][2]) 可是这时候的h[2][1]我们还没有枚举到啊
因为这时候是一层一层开始枚举的 所以这样是会出错的
因此我们需要从j开始枚举 也就是一列一列开始枚举 这样就不会出错了

对于这次的cf 我感觉自己发挥的不是很好 又是只写了一道题(真的垃圾)
多说无益 自己好好努力吧!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值