2021-07-06 JZYZ暑期集训Day1上午 枚举与模拟

这篇博客探讨了两个算法题目,分别是CF1225C的p-binary问题和CF1214A的货币兑换问题。在p-binary问题中,分析了如何寻找最小的x满足特定等式,并解释了当n-tp小于t时无法表示的原因。在货币兑换问题中,提出了先用所有卢布兑换美元,然后用剩余卢布兑换欧元的策略来最小化剩余卢布的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

[CF1225C] p-binary

给定整数n,p,求最小的x使其满足
∑ i = 1 x ( 2 k + p ) = n \sum_{i=1}^{x}(2^k+p)=n i=1x(2k+p)=n
其中k可以是任意的自然数。

输入格式:n,p(1<=n<=10^9,-1000<=p<=1000)

输出格式:

找不到这样的x输出-1,否则输出x。

样例:
input1:24 0 output:2

input2:24 1 output:3

分析:
这个题设最后的答案为t,原式可以展开,成为
( 2 k 1 ) + ( 2 k 2 ) . . . + ( 2 k t ) + t p = n (2^k1)+(2^k2)...+(2^kt)+tp=n (2k1)+(2k2)...+(2kt)+tp=n

( 2 k 1 ) + ( 2 k 2 ) . . . + ( 2 k t ) = n − t p (2^k1)+(2^k2)...+(2^kt)=n-tp (2k1)+(2k2)...+(2kt)=ntp
刚好能被t个二进制表示。

如果n-tp<t,则无法表示,因为每个二进制最小为2^0=1,t个二进制最小是t。同时,t只可大不可小。因为t不能比n-tp的二进制的1个数少。

#include<bits/stdc++.h>
using namespace std;
int main(){
	//freopen("pbinary.in","r",stdin);
	//freopen("pbinary.out","w",stdout);
	int n,p;
	cin>>n>>p;
	for(int i=0;i<=10000;i++){ //i为上述的t,即最后的答案。
		int tmp=n-p*i,cnt=0;//tmp为上述的n-tp。
		while(tmp){
			cnt=cnt+tmp%2;
			tmp=tmp/2;//一直短除法求二进制
		}
		if(cnt<=i && n-p*i){ //符合情况
			cout<<i<<endl;
			return 0;
		}
	}
	cout<<-1<<endl;//不符合情况
	return 0;
}

[CF1214A] Optimal Currency Exchange

Andrew参加了Olympiad of Metropolises,现准备回国,需要兑换货币。

现有如下面额的美元纸币:1,2,5,10,20,50,100,以及以下面额的欧元纸币:5,10,20,50,100,200(注意,不考虑500欧元纸币,因为在货币兑换窗口很难找到这种)。已知兑换1美元需要d卢布,1欧元需要e卢布,而Andrew有n卢布。

他可以兑换任意数量的美元和欧元(一种纸币可以兑换多次,可以美元和欧元混合),并且,他希望使兑换后手里剩余的卢布数尽可能少。请你写一个程序帮他解决问题(只需求出最小的剩余卢布数)。

输入格式:
3行,3个整数n,d,e
输出格式:
1行,最小剩余量

数据范围:
1<=n<=10^8
30<=d,e<=100

样例:
input1:100 60 70
output1:40

input2:410 55 70
output2:5

思路:我们看题不难发现,美元纸币的款项都是1块组成的,欧元纸币的款项都是5块钱组成的(倍数)。
那么先把钱全去买美元,然后再把剩下的钱买欧元就行了,最后剩下的钱,输出就行了

#include<bits/stdc++.h>
using namespace std;
int main(){
	freopen("exchange.in","r",stdin);
	freopen("exchange.out","w",stdout);
	int n,d,e,ans=100000000;//100 60 70
	cin>>n>>d>>e;
	e=e*5;//350
	for(int i=1;i<=n/d;i++){ //i=1 
		if(ans>(n-i*d)%e) ans=(n-i*d)%e;//ans=(100-1*60)%70 40%70
	}
	cout<<ans<<endl;
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值