p8584 探索未知

p8584 探索未知

【题目描述】

通道上有许多路牌。第 i 个路牌上写有一个分数 bi​、ai​​ 和一个分数运算符 + 或 −。

一开始,你的手上拿着一个数字 0。你沿着通道向后走。每走到一个路牌,会用手上的数和路牌上的分数,用路牌上的运算符号进行计算,并把得到的新数拿在手中(丢弃掉手中原来的数)。值得注意的是,如果你手中计算得到的数不是整数,则会保留既约分数的形式;否则直接保留整数形式。

现在你想知道,当你走到通道的末端时,手中拿着的数是多少?

【输入】

第 1 行共一个正整数 nn 表示通道内共有 n 个路牌。

第 2∼n+1 行每行三个正整数 ai​,bi​,opti​ 表示第 i 个路牌上写着的分数为 bi​、ai​​,运算符为 opti​。

其中,+,- 两种运算分别用 1,2 代替。

【输出】

共一行一个数。

若最终的结果可以保留为整数,则输出一个整数 ansans 表示结果。

结果可能出现负数,此时需要保留负号。例如,若结果为 −11451/4​,那么需要输出 -11451/4

对于 100% 的数据,保证  1≤n≤10^3,10000≤a≤1000, 10000

解题思路

这个题我刚开始是用约分的公式直接求的,每一步约分后再把公因数约掉。

这个题的数据范围:计算过程中数字的大小不超过  2×10^9,在分母相乘的过程中,最大的范围不会超过 4×10^18,所以要用 long long 的数据范围。

然后把负号考虑进来,当分子和分母同时为负数、分子是正数且分母是负数时,就要根据写分式的原则,把负号约掉或者提到分子前面。

这样子的思路是 50 分,可能在约分时没有处理得合适。

所以用辗转相乘法:

也就是求最大公约数和最小公倍数。

long long gec(long a,long b){//最大公倍数 
	if(b>0)
	return gec(b,a%b);
	else
	return a;
}
long long fun(long long a,long long b){//最小公倍数 
	return a*b/gec(a,b);
}

把最大公约数传入主函数,然后就是两个分式通分的过程,再根据每一行的最后一个数(运算符 c)算出当前的分子。然后在每次加完和减完后可以再通过最小公倍数将计算的结果化简。这一步如果省略也会出错!

代码如下:

#include
#include
long long mit(long a,long b){//最大公倍数 
	if(b>0)
	return mit(b,a%b);
	else
	return a;
}
long long mat(long long a,long long b){//最小公倍数 
	return a*b/mit(a,b);
}
int main()
{
	long long  son=0,mother=1;//初始化 
	long long n,a,b,c,i,j;
	scanf("%lld",&n);
	for(i=0;i0)
	printf("%lld/%lld\n",-son,-mother);
	else
	printf("%lld/%lld\n",son,mother);
	return 0;
}

01背包问题 

p8584 探索未知_第1张图片

 二维 dp 数组:

#include
#include
using namespace std;
int dp[1005][1005];
int main(){
	int n,v,i,j,x,y;
	scanf("%d%d",&n,&v);
	for(j=1;j<=n;j++){
		scanf("%d%d",&x,&y);
		for(i=0;i<=v;i++){
			if(i

一维 dp 数组:

#include
#include
using namespace std;
int dp[1005];
int main(){
	int i,j,x,y,v,n;
	scanf("%d%d",&n,&v);
	for(i=1;i<=n;i++){
		scanf("%d%d",&x,&y);
		for(j=v;j>0;j--){
			if(j>=x)
			dp[j]=max(dp[j],dp[j-x]+y);
		}
	}
	printf("%d\n",dp[v]);
	return 0;
}

p1706 全排列

p8584 探索未知_第2张图片 

#include
int book[15];
int use[10];
void print(int n){
	for(int i=0;i

你可能感兴趣的:(题组,辗转相除法,c,分数)