【Contest 2050 and Codeforces Round #718 (Div. 1 + Div. 2)】Codeforces-1517

A. Sum of 2050

第一眼以为dp,憨憨写了五分钟发现d不出来,我好傻qaq
这道题只讨论 2050 ∣ n 2050\mid n 2050n的情况。
假设 n 为 n为 nm位十进制数,则有
n = k 1 ∗ 2050 ∗ 1 0 m − 4 + k 2 ∗ 2050 ∗ 1 0 m − 5 + k 3 ∗ 2050 ∗ 1 0 m − 6 + . . . + k m − 4 ∗ 2050 ∗ 1 0 0 n=k_1*2050*10^{m-4}+k_2*2050*10^{m-5}+k_3*2050*10^{m-6}+...+k_{m-4}*2050*10^{0} n=k1205010m4+k2205010m5+k3205010m6+...+km42050100
其中 k i k_i ki可能有多种可能,要使得 ∑ i = 1 n k i \sum_{i=1}^n k_i i=1nki最小,则必有 ∀ k i ≤ 9 \forall k_i\leq9 ki9。即只要从最大的 2050 ∗ 1 0 k 2050*10^k 205010k减下去就行。

void solves(){
	ll n;cin>>n;
	if(n<2050){
		cout<<-1<<endl; return ;
	}
	int cnt=0;
	while(n){
		ll i=2050;
		while(i<=n)i*=10;
		i/=10;
		n-=i;
		cnt++;
		if(n<2050&&n){
			cout<<-1<<endl;return ;
		}
	}
	cout<<cnt<<endl;
}

B. Morning Jogging

认真读一下题意,思维非常简单,没什么好分析的,但是代码不太好写,写了快1h才调出来wssb 。记列数为m,取最小的m个数字,要使得每一列都有一个这m个数字即可。如样例:
2 3 4
1 3 5
⇓ \Downarrow
2 3 4
5 3 1
我个人感觉我的写法复杂乱乱的且sb,不知道有没有更好的写法

void solves(){
	int n,m; cin>>n>>m;
	int tot=0;
	for(int i=0;i<n;++i){
		for(int j=0;j<m;++j){
			cin>>mp[i][j];
			a[tot++]=mp[i][j];
			vis[i][j]=0;
		}
	}
	sort(a,a+tot);
	int mid=a[m-1];
	int s=0;
	for(int i=0;i<tot;++i){
		if(a[i]<mid) s++;
	}
	s=m-s;
	memset(cnt,0,sizeof(cnt));
	for(int i=0;i<n;++i){
		for(int j=0;j<m;++j){
			if(mp[i][j]<mid){
				vis[i][j]=1;
				cnt[j]++;//统计原本每一列中有多少个最小的m个数字
			}
			if(mp[i][j]==mid&&s){
				vis[i][j]=1;
				cnt[j]++;//统计原本每一列中有多少个最小的m个数字
				s--;
			}
		}
	}
	for(int j=0;j<m;++j){//先逐个询问每一列
		if(!cnt[j]){ //如果这一列没有最小的数字
			for(int i=0;i<m;++i){ //就找一列有的并且个数>1的
				if(cnt[i]>1){
					for(int k=0;k<n;++k){ //再遍历可swap的这一列 然后找到那个可swap的数
						if(vis[k][i]){
							swap(mp[k][i],mp[k][j]);
							vis[k][i]=0;
							vis[k][j]=1;
							cnt[i]--;
							cnt[j]++;
							goto ok;
						}
					}
				}
			}
		}
		ok: ;
	}
	for(int i=0;i<n;++i){
		for(int j=0;j<m;++j) cout<<mp[i][j]<<" ";
		cout<<endl;
	}
}

C. Fillomino 2

一开始真的是思维受限,想着一条对角线一条对角线直接填充,写了半天还是wa了。其实想明白思路后代码其实很简单。
从最下面开始,每一个元素尽量向下填充慢慢往上铺即可。

const int N=5e2+7;
int mp[N][N],vis[N][N],cnt[N];
int n;
void dfs(int c,int num,int x,int y){
	if(c==0||x<1||y<1) return ;
	if(x==n||mp[x+1][y]){
		mp[x][y-1]=num;
		dfs(c-1,num,x,y-1);
	} else{
		mp[x+1][y]=num;
		dfs(c-1,num,x+1,y);
	}
	
}
void solves(){
	cin>>n;
	for(int i=1;i<=n;++i){
		cin>>mp[i][i];
		cnt[i]=mp[i][i]-1;
	}
	for(int i=n;i>=1;--i) dfs(cnt[i],mp[i][i],i,i);
	for(int i=1;i<=n;++i){
		for(int j=1;j<=i;++j) cout<<mp[i][j]<<" ";cout<<endl;
	}
}

感觉这场思维还是比较简单的,就看想不想得到了。主要我还是太菜了qaq

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值