日常分享题目

火柴棒等式

题目描述

现在我们给昆昆n根火柴棍,请算算以昆昆的聪明才智昆昆可以拼出多少个形如“A+B=C”的等式?等式中的A、B、C是用火柴棍拼出的整数(若该数非零,则最高位不能是0)。用火柴棍拼数字0-9的拼法如图所示:

img

注意:

  1. 加号与等号各自需要两根火柴棍
  2. 如果A≠B,则A+B=C与B+A=C视为不同的等式(A,B,C>=0)
  3. n根火柴棍必须全部用上

输入格式

一个整数n(n<=24)。

输出格式

一个整数,能拼成的不同等式的数目。

输入输出样例

输入

14

输出

2

输入

18

输出

9

说明/提示

【输入输出样例1】

2个等式为0+1=1和1+0=1。

【输入输出样例2】

9个等式为:

0+4=4
0+11=11
1+10=11
2+2=4
2+7=9
4+0=4
7+2=9
10+1=11
11+0=11

由于1111+1=1112已经用了25根小棒,已经超过了题目24根小棒的数据范围,所以可以直接枚举相加的两个数,上界为1111,

#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>

using namespace std;
int a[10]={6,2,5,5,4,5,6,3,7,6};
//'=''+'==2
//0==6
//1==2
//2==5
//3==5
//4==4
//5==5
//6==6
//7==3
//8==7
//9==6
int matchs(int num){    //一个用来计算一个数需多少个火柴棒的函数
         int i,k=0;       //K是火柴棒的数量
         for(i=num;i!=0;i/=10)k+=a[i%10];    //将这个数字每一位的火柴棒的数量都计算出来
         if(num==0)k+=a[0];      //有一种特殊情况:数字为0此时不会执行上述程序,所以加一个
         return k;
}
int main() 
{
    int n,res = 0;
    cin >> n;
    for(int i = 0;i<1000;i ++)
        for(int j = 0;j <1000;j++)//表示范围在1000左右 
        {
        	if(matchs(i) + matchs(j) +matchs(i+j)+4 == n) res++;
		 } 
        
    cout << res <<endl;
    return 0;
}

王姐拼木棒

题目背景

上道题中,王姐劈了一地的木棒,现在她想要将木棒拼起来。

题目描述

有 n 根木棒,现在从中选 4 根,想要组成一个正三角形,问有几种选法?

答案对 10^9+7 取模。

输入格式

第一行一个整数 n。

第二行 n 个整数,第 i 个整数 ai 代表第 i 根木棒的长度。

输出格式

一行一个整数代表答案。

输入输出样例

输入

4 
1 1 2 2

输出

1

说明/提示

数据规模与约定
  • 对于 30%30% 的数据,保证n≤5×10^3。
  • 对于 100%100% 的数据,保证1≤n≤105,0≤ai≤5×103。

题里面说,4根棍子拼成一个正三角形(等边三角形)

别像我题都不看清楚就在那里分析半天最后才看到这个!!!

若设这四根棍子长度为a,b,c,d且a≥b>c≥d

那很容易得到 (真的很容易):

a=b=c+d
排列组合在这里插入图片描述

#include<iostream>
#include<fstream>
#include<cstdio>
#include<cmath>
#include<queue>
#include<string>
#include<cstring>
#include<string.h>
#include<algorithm>
#include<iomanip>
using namespace std;
int n,b[5010],a[1000010],minn=1e9,maxx;
long long ans;
const int mod=1e9+7;
int main()
{
	cin>>n;
	for(int i=1; i<=n; i++)
	{
		cin>>a[i];//输入
		minn=min(minn,a[i]);//找出最小的边
		maxx=max(maxx,a[i]);//找出最大的边
		b[a[i]]++;//数组记录边数
	}
	
	for(int i=minn+1; i<=maxx; i++)//这里从最小量+1开始枚举,是因为最小量不可能有两个比它更小的两组成
	{
		if(b[i]>1)//如果这个数字有一个以上,外层有多个相同的边
			for(int j=minn; j<=i/2; j++)//从最小边开始枚举,注意边算边取模
				if(b[j]>=1&&b[i-j]>=1)//如果他可以被两个比他小的两组成
				{//这里一定要清楚i和j表示的是长度而不是个数
					if(j*2!=i)ans=(ans+(b[i]*(b[i]-1)/2)*b[j]*b[i-j]%mod)%mod;//统计,如果两边不相同
					//选两条Cn2,剩下不同的各选一条Cn1
					else if(b[j]>1)ans=(ans+((b[i]*(b[i]-1)/2)*(b[j]*(b[j]-1)/2)%mod)%mod)%mod;//统计,相同
					//各选两条cn2
				}
	}
	cout<<ans%mod;//输出
	return 0;
}

烤乳猪

题目描述

烤乳猪是一种流行的美食。为了做好烤乳猪,厨师必须谨慎选择食材,以在保持传统风味的同时尽可能获得最全面的味道。星瑶有 n 种可支配的配料。对于每一种配料,我们知道它们各自的酸度 s 和苦度 b。当我们添加配料时,总的酸度为每一种配料的酸度总乘积;总的苦度为每一种配料的苦度的总和。

众所周知,美食应该做到口感适中,所以我们希望选取配料,以使得酸度和苦度的绝对差最小。

另外,我们必须添加至少一种配料,因为没有任何食物以水为配料的。

输入格式

第一行一个整数 n,表示可供选用的食材种类数。

接下来 n 行,每行 2个整数 si 和 bi,表示第 i 种食材的酸度和苦度。

输出格式

一行一个整数,表示可能的总酸度和总苦度的最小绝对差。

输入输出样例

输入

1
3 10

输出

7

输入

2
3 8
5 8

输出

1

输入

4
1 7
2 6
3 8
4 9

输出

1

说明/提示

数据规模与约定

对于 100% 的数据,有 1≤n≤10,且将所有可用食材全部使用产生的总酸度和总苦度小于 1×109,酸度和苦度不同时为 1和 0。

注意数据范围,一道简单的dfs

#include<bits/stdc++.h>	
using namespace std;
long long int s[20],b[20],f[20];
long long int n,j,c=1,y=0,ans=1000000010;
//s表示酸度,b表示甜度,f记录是否查找
//c记录酸度,y记录甜度
void dfs(int x)
{
	if(x>n)		//最多选n种调料,超过返回
	{
		return;
	}
	else
	{
		for(int i=1;i<=n;i++)
		{
			if(f[i]==0)		//没有查找过的才操作
			{
				c *= s[i];
				y += b[i];
				ans=min(ans,abs(c-y));	//取最小值
				f[i]=1;		//记录
				dfs(x+1);
				//回溯
				f[i]=0;		//取消记录
				c/=s[i];
				y-=b[i];
			}
		}
	}
}
int main()
{
	cin>>n;
	for(int i=1;i<=n;i++)
	{
		cin>>s[i]>>b[i];
	}
	dfs(1);
	cout<<ans;
}

阿晨考前临时抱佛脚

题目背景

阿晨的大学生活非常的颓废,平时根本不学习。但是,临近期末考试,他必须要开始抱佛脚,以求不挂科。

题目描述

这次期末考试,阿晨需要考 44 科。因此要开始刷习题集,每科都有一个习题集,分别有 s*1,s2,s3,*s4道题目,完成每道题目需要一些时间,可能不等。

阿晨有一个能力,他的左右两个大脑可以同时计算 2 道不同的题目,但是仅限于同一科。因此,阿晨必须一科一科的复习。

由于 阿晨还急着去处理java的 bug,因此他希望尽快把事情做完,所以他希望知道能够完成复习的最短时间。

输入格式

本题包含 5行数据:第 1 行,为四个正整数 s_1,s_2,s_3,s_4s1,s2,s3,s4。

第 2 行,为 A1,A2,…,As1 共 s1 个数,表示第一科习题集每道题目所消耗的时间。

第 3 行,为 B1,B2,…,Bs2 共s2 个数。

第 4 行,为 C1,C2,…,Cs3 共s3 个数。

第 5 行,为 D1,D2,…,Ds4 共s4 个数,意思均同上。

输出格式

输出一行,为复习完毕最短时间。

输入输出样例

输入

1 2 1 3		
5
4 3
6
2 4 3

输出

20

说明/提示

1≤s1,s2,s3,s4≤20。

1≤A1,A2,…,As1,B1,B2,…,Bs2,C1,C2,…,Cs3,D1,D2,…,Ds4≤60。

被贪心骗了奶奶滴

感觉是dp,对于一道题只有两个状态,一是加到左脑,二是加到右脑,所以是01背包

这里还可以用另一个思想,将一边的脑子加到最接近一半则另一边脑子时间就是正解

保证比t/2小,又要使取得的价值尽量大,可以转化为一个费用与价值相同的背包问题。背包大小为t/2,一个题目的费用和价值相等,都是所耗的时间。

假设背包求得的最大价值为v,显然另一个脑耗时为t-v,则总耗时为max(v,t-v)。

#include<bits/stdc++.h>
using namespace std;
int a[5],i,j,k,sum,t,homework[21],dp[2501];
int main(){
	for(i=1;i<=4;i++)
		cin>>a[i];
	for(i=1;i<=4;i++){
		sum=0;	
		for(j=1;j<=a[i];j++)
			{cin>>homework[j];//输入
			sum+=homework[j];}//总时间累加,这个相当于就是背包
		for(j=1;j<=a[i];j++)
			for(k=sum/2;k>=homework[j];k--)//只要是总和的一半
				dp[k]=max(dp[k],dp[k-homework[j]]+homework[j]);//01背包
		t+=sum-dp[sum/2];//累加为另一个脑子,最接近一半,肯定是小于等于一半的
		if(i!=4) memset(dp,0,sizeof dp);
	}
	cout<<t;//输出
	return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值