问题 F: 校门内的树
题目描述
FZYZ 大门的左侧有一排 n 棵树木。它们按照距离的远近排列,第 1 棵树的高度为 a1 米,第 2 棵树木的高度为 a2 米,第 3 棵树木的高度为 a3 米,……,第 n 棵树木的高度为 an米。
为了给同学们以积极向上的感觉,一些同学自发地决定对树木进行修剪,使得树木呈现上升的趋势。具体地说,他们希望对树木进行修剪和整理,使得修剪之后的树木高度 b1,b2,b3,…,bn 米且满足 b1 他们不仅可以对较高的枝条进行修剪使其高度减小,还可以通过枝条的加固使得树木的高度增加,而且可以使树木的高度减小和增加任意的高度,但一定得是整数(单位为米),而且最后树的高度必须大于零。然而,树木的整理只能在课间进行,因此他们没有太多的时间。对于一棵树,将其修剪使其高度减少 x 米需要花费 x 分钟的时间,将其整理加固使其高度增加 x 米也需要花费 x 分钟的时间。 参加这次活动的同学超过 n 个,因此所有树木可以同时得到修剪或整理。请你帮他们求出,最少要花费多少的时间可以修剪使得树木递增。注意:花费的总时间取决于最后完成修剪或整理的同学。 思路: 问题 A: 报数游戏 题目描述 思路: 问题 B: 趣味填空 题目描述 思路: 问题 C: 杨辉三角 题目描述 输入 思路: 问题 D: 换座位 题目描述 思路: 问题 E: 神仙贷款 题目描述 思路: 化简之后可以得到这样一个式子 1 - a/b * p
输入
第一行包含 1 个整数 n,表示树木的个数。
第二行包含 n 个整数 a1,a2,a3,…,an,表示第 1 棵树的高度、第 2 棵树的高度、第 3 棵树的高度、……、第 n 棵树的高度。
输出
一行包含1个整数,表示能修剪使得树木具有“向上的趋势”的最短时间。
样例输入 Copy
【样例 1 】
3
9 5 11
【样例 2 】
2
5 8
【样例 3 】
5
1 1 1 1 1
【样例 4 】
5
548 47 58 250 2012
样例输出 Copy
【样例 1 】
3
【样例 2 】
0
【样例 3 】
4
【样例 4 】
251
提示
对于 40% 的数据,n≤2;
对于 60% 的数据,n≤15;
对于 80% 的数据,ai≤3000;
对于 100% 的数据,n≤50,ai≤10^9。
很明显的最大值最小,用二分解决
这里还有一点点贪心的思想,我们希望第一棵树尽量的矮,这样的话后面的树可以修剪的就相对要少,花费时间就少,于是我们判断第一棵树高度 - x是否大于1,如果小就取第一棵树高度为1。剩下的从第二棵树开始循环,每次判断当前树的高度 - x是否大于前一棵树的高度+1,我们希望尽量要小,所以如果大于就直接取上一棵树高度+1。每次二分去寻找这个答案即可int a[60],b[60];
int n,ans,maxx;
int check(int x)
{
if(x < 0) return 0;
b[1] = a[1]-x>1?a[1]-x:1;
//我们希望第一棵树尽量小
for(int i=2;i<=n;i++)
{
if(a[i]+x <= b[i-1]) return 0;
//没法加高
b[i] = a[i]-x<b[i-1]+1?b[i-1]+1:a[i]-x;
//如果减去这个相同的数比前一个高度+1矮,就只能取前一个高度+1,保证是整数
}
return 1;
}
int main()
{
n = read();
for(int i=1;i<=n;i++)
{
cin >> a[i];
maxx = max(maxx,a[i]);//找最大高度
}
int r = maxx+10,l = -1;
//找到中间高度二分答案
while(l+1 < r)
{
int mid = (l+r)/2;
if(check(mid)) r = mid;
//说明可以花费更小
else l = mid;
}
cout << r << endl;
return 0;
}
在一次班队活动上,班主任张老师设计了一个“报数游戏”的活动。游戏规则是这样的:每次游戏有甲、乙二位同学参加,甲按 1—a 的顺序循环报数,乙按 1—b 的顺序循环报数。两人同时开始,并以同样的速度报数,当两人都报了 n 个数时,统计出两人同时报相同数的次数,先算对者获胜。现在老师请你来做裁判,算出每次游戏的正确答案。
输入
共二行。第一行仅有一个整数 n(n<=100),第二行有二个整数a、b,中间用空格间隔(2<=a、b<=10)。
输出
只有一行,有一个整数,表示两人同时报相同数的次数。
样例输入 Copy
10
2 3
样例输出 Copy
4
这个题一层循环即可,在一层大循环中定义两个变量i 和 j控制报数,相等就ans++,一旦满足i == a,就让i = 0,同理j也是这样处理int n,a,b,ans,cnt;
int i,j;
int x[105];
int main()
{
cin >> n;
cin >> a >> b;
while(n--)
{
i++,j++;
if(i == j) ans++;
if(i == a) i = 0;
if(j == b) j = 0;
}
cout << ans << endl;
return 0;
}
小华的寒假作业上,有这样一个趣味填空题:
给出用等号连接的两个整数,如“1234=492”。当然,现在这个等式是不成立的。
请你在等号左边整数中的某个位置尝试插入一个乘号,看有没有可能让等式成立。以上
面的式子为例,如果写成 123*4=492,这样就正确了。
现在请你编写一个程序来解决它。
输入
输入只有那个不成立的等式,且等号两边的整数均不会超过
2000000000。
输出
输出只有一行。如果存在这样的方案,请输出那个正确的式子;如果
不存在解决方案,请输出“Impossible”(引号中的部分)。
样例输入 Copy
1234 = 492
样例输出 Copy
123 * 4 = 492
提示
测试数据保证不会出现多个解决方案
这个题和昨天那道整数拆分的题思想一样,但这道题还需要一层循环,首先先把等号右边的字符串转换成数字,然后一位位拆分左边的字符串,比较即可string s;
ll x,p,q,n;
int main()
{
cin >> s;
p = 0,q = 0,x = 0;
for(int i=0;i<s.size();i++)
{
if(s[i] == '=') n = i;
}
for(int i=n+1;i<s.size();i++)
{
x = x*10+(s[i]-48);
}
for(int i=0;i<n;i++)
{
p = p*10+(s[i]-48);
q = 0;
for(int j=i+1;j<n;j++)
q = q*10+(s[j]-48);
if(p*q == x)
{
printf("%lld*%lld=%lld\n",p,q,x);
return 0;
}
}
printf("Impossible\n");
return 0;
}
杨辉三角,又称贾宪三角形、帕斯卡三角形,由北宋人贾宪约于 1050 年在《释锁算术》中首先提出,下图显示的是杨辉三角的前 6 行。仔细研究杨辉三角,我们可以发现它的许多性质。
亲爱的同学,现在请你也来研究一下杨辉三角,并求出杨辉三角中第 m 行的第 n个数(按从左往右的顺序)。
只有一行,有二个整数m和n(m<=35),数间用一个空格隔开。
输出
只有一行,有一个整数,表示杨辉三角中第m行的第n个数。
样例输入 Copy
6 3
样例输出 Copy
10
写出一个杨辉三角的矩阵即可int m,n;
ll a[40][40];
int main()
{
cin >> m >> n;
for(int i=1;i<=35;i++)
{
a[i][1] = a[i][i] = 1;
}
for(int i=3;i<=35;i++)
{
for(int j=2;j<=(i-1)/2+1;j++)
{
a[i][j] = a[i][i-j+1] = a[i-1][j]+a[i-1][j-1];
}
}
printf("%lld\n",a[m][n]);
return 0;
}
聪聪和同学们正在玩这样一个换座位的游戏:班上共有2n个少先队员,开始时每个少先队员坐在自己的板凳上排成一队,由聪聪开始击鼓,每次击鼓开始时,前n个同学坐到第2、4、…、2n个板凳上,后n个同学坐到第1、3、…、2n-1个板凳上,击鼓结束时坐错或者还没有坐到对应板凳上的同学就要接受惩罚——表演一个节目,并按规定坐好。聪聪不断的击鼓然后停顿后又击鼓…,同学们都觉得这个游戏很好玩,但是当游戏结束时,同学们傻眼了,由于每位同学的板凳都差不多,他们找不到自己的板凳了。
而聪聪这时反应特别快,他说经过一定次数的换座位,每位同学一定能回到自己的板凳的。那么这个次数最少是多少呢?你会计算吗?
输入
共一行,一个正整数n(1≤n≤10000)。
输出
共一行,一个正整数,表示每位同学都回到自己板凳的最少换座位次数。
样例输入 Copy
10
样例输出 Copy
6
定义两个数组分别存储变换前和后的位置,模拟即可,注意数据范围ll n,ans;
int a[maxn],b[maxn];
int judge(int b[])
{
for(int i=1;i<=2*n;i++)
{
if(b[i] != i) return 0;
}
return 1;
}
int main()
{
n = read();
for(int i=1;i<=2*n;i++)
{
a[i] = i;
b[i] = i;
}
for(int k=0;;k++)
{
ans++;
for(int i=1;i<=n;i++) b[2*i] = a[i];
for(int i=n+1;i<=2*n;i++) b[(i-n)*2-1] = a[i];
if(judge(b))
{
cout << ans << endl;
return 0;
}
else
{
for(int i=1;i<=2*n;i++)
a[i] = b[i];
}
}
return 0;
}
神仙由于刚到凡间故手上缺钱,于是她去银行贷款了。因此,她在贷款之后,在一段时间内将不得不每月偿还固定的分期付款。这个问题要求计算神仙向银行支付的利率。假设利率按月累计。
输入
输入仅一行包含三个用空格隔开的正整数。第一个整数表示贷款的原值,第二个整数表示每月支付的分期付款金额,第三个整数表示分期付款还清贷款所需的总月数。
输出
输出一个实数,表示该贷款的月利率(用百分数表示),四舍五入精确到0.1%。
样例输入 Copy
1000 100 12
样例输出 Copy
2.9
题目说利率按月累计,也就是说假设利率是p,第一个月要还钱 = 每个月支付的分期付款金额 / (1+p),第二个月要还的钱 = 每个月支付的分期付款金额 / (1+p)^2,所以这样计算下来总金额
k
a = ∑ { b * [1 / (1+ans) ] ^ i }
i=1
很明显这个式子具有单调性,所以我们去二分这个答案
注意题目说要用百分数表示,并且保留一位小数double n,m,k,l,r;
bool pd(double x)
{
return (pow(1.0/(1.0+x),k)>=1-a/b*x);
}
int main()
{
cin >> a >> b >> k;
l = 0;r = 10;
while(r-l >= 0.0001)
{
double mid = (l+r)/2;
if(pd(mid)) r = mid;
else l = mid;
}
printf("%.1f\n",l*100);
return 0;
}