day10蓝桥algo 22\23\25\26\28\37

-22. 数的划分!!!


问题描述
  将整数n分成k份,且每份不不能为空,任意两份不不能相同(不不考虑顺序)。
  例例如:n=7,k=3,下⾯面三种分法被认为是相同的。
  1,1,5; 1,5,1; 5,1,1;
  问有多少种不不同的分法。
输⼊入格式
  n,k
  输出格式
  ⼀一个整数,即不不同的分法
样例例输⼊入
7 3
样例例输出
4 {四种分法为:1,1,5;1,2,4;1,3,3;2,2,3;}
数据规模和约定
  6<n<=200,2<=k<=6

思考:
通过递归进行(我只能说递归是yyds)
front-前一次的递归的结果(上一次划分的数)
n-剩余划分的数
k-当前还剩多少步
把n分成了k分,i需要从1循环到n/k。
这样才能保证得到的划分方式是不递减的,才能保证不不会有重复的情况产⽣

这个循环很有意思,反着来的

#include<iostream>
using namespace std;
int count;
void divid(int front,int n,int k){
	if(k==1)
	{
		count++;
		return ;
	}
	for(int i=front;i<=n/k;i++)
		divid(i,n-i,k-1);
}

int main(){
	int n,k;
	scanf("%d %d",&n,&k);
	divid(1,n,k);
	printf("%d",count);
	return 0;
	
	
}

ALGO-23. ⼀一元三次⽅方程求解*


问题描述
有形如:ax3+bx2+cx+d=0 这样的⼀一个⼀一元三次⽅方程。给出该⽅方程中各项的系数(a,b,c,d 均为实
数),并约定该⽅方程存在三个不不同实根(根的范围在-100⾄至100之间),且根与根之差的绝对值>=1。要求
三个实根。
输⼊入格式
四个实数:a,b,c,d
输出格式
由⼩小到⼤大依次在同⼀一⾏行行输出这三个实根(根与根之间留留有空格),并精确到⼩小数点后2位
样例例输⼊入
1 -5 -4 20
样例例输出
-2.00 2.00 5.00
数据规模和约定
|a|,|b|,|c|,|d|<=10

思考:
就是用二分法进行求解
注意循环里面的i是用int型

#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;
double a,b,c,d;
double f(double x) 
	{return a*pow(x,3)+b*pow(x,2)+c*x+d;
	}
double find(double x,double y){
	if(y-x<0.0001) return x;
	double mid=(x+y)/2;
	if(f(mid)*f(x)>0) return find(mid,y);
	else return find(x,mid);
}
int main(){
	
	cin>>a>>b>>c>>d;
	for(int i=-100;i<=100;i++)
	{
		if(f(i)==0)
			printf("%.2f ",i*1.0); 
		else if(f(i)*f(i+1)<0) printf("%.2f",find(i,i+1));
	}
	return 0;
}

ALGO-25. Car的旅⾏行行路路线!


问题描述
⼜又到暑假了了,住在城市A的Car想和朋友⼀一起去城市B旅游。她知道每个城市都有四个⻜飞机场,分别位
于⼀一个矩形的四个顶点上,同⼀一个城市中两个机场之间有⼀一 条笔直的⾼高速铁路路,第I个城市中⾼高速铁路路
了了的单位⾥里里程价格为Ti,任意两个不不同城市的机场之间均有航线,所有航线单位⾥里里程的价格均为t。
那么Car应如何安排到城市B的路路线才能尽可能的节省花费呢?她发现这并不不是⼀一个简单的问题,于是
她来向你请教。
找出⼀一条从城市A到B的旅游路路线,出发和到达城市中的机场可以任意选取,要求总的花费最少。
输⼊入格式
的第⼀一⾏行行有四个正整数s,t,A,B。
S表示城市的个数,t表示⻜飞机单位⾥里里程的价格,A,B分别为城市A,B的序号,(1<=A,B<=S)。
接下来有S⾏行行,其中第I⾏行行均有7个正整数xi1,yi1,xi2,yi2,xi3,yi3,Ti,这当中的(xi1,yi1),
(xi2,yi2),(xi3,yi3)分别是第I个城市中任意三个机场的坐标,T I为第I个城市⾼高速铁路路单位⾥里里程的价
格。
输出格式
共有n⾏行行,每⾏行行⼀一个数据对应测试数据,保留留⼀一位⼩小数。
3 10 1 3
1 1 1 3 3 1 30
2 5 7 4 5 2 1
8 6 8 8 11 6 3

样例输出

47.6
数据规模和约定
0<S<=100,
思考:
1、题目说一个城市会有4个机场,但是题目只有3个顶点,所以通过垂直关系找到第四个顶点
再把所以点放在同一个数组里面
2、获取价格,城市内部的通过高速进行,城市与城市之间的通过飞机
3、多源遍历,先pri[i][j]==pri[j][i]获取亮点之间的价格
再通过第三个点进行,看看是否经过中间商会更便宜

 #include <bits/stdc++.h>
 using namespace std;
  
 #define MAXN 405
 #define INF 0x7f7f7f7f 
  
  int n, s, t;
  double P, p[MAXN], tx[5], ty[5], x[MAXN], y[MAXN], pri[MAXN][MAXN], ans = INF;
  
 double calc(int a, int b, int c) {
     if (tx[a] == tx[b] && ty[b] == ty[c] || tx[c] == tx[b] && ty[a] == ty[b]) return -1;
     return (ty[a] - ty[b])/(tx[a] - tx[b]) * (ty[b] - ty[c])/(tx[b] - tx[c])
 }
 
 double getp(int a, int b) {
     return sqrt((x[a] - x[b]) * (x[a] - x[b]) + (y[a] - y[b]) * (y[a] - y[b])) * (a / 4 == b / 4 ? p[a / 4] : P);
 }
 
 int main() {
     cin >> n >> P >> s >> t;
     for (int i = 1; i <= n; i++) {
         for (int j = 1; j <= 3; j++)
             cin >> tx[j] >> ty[j];
         if (calc(1, 2, 3) == -1) {
             tx[4] = tx[1] + tx[3] - tx[2];
             ty[4] = ty[1] + ty[3] - ty[2];
         }
         else if (calc(2, 1, 3) == -1) {
             tx[4] = tx[2] + tx[3] - tx[1];
             ty[4] = ty[2] + ty[3] - ty[1];
         }
         else {
             tx[4] = tx[1] + tx[2] - tx[3];
             ty[4] = ty[1] + ty[2] - ty[3];
         }
         for (int j = 1; j <= 4; j++) {
             int o = i * 4 + j - 5;
             x[o] = tx[j], y[o] = ty[j];
         }         cin >> p[i - 1];
     }
     memset(pri, INF, sizeof(pri));
     for (int i = 0; i < n * 4; i++)
         for (int j = 0; j < n * 4; j++)
            pri[i][j] = pri[j][i] = getp(i, j);
     for (int i = 0; i < n * 4; i++)
         for (int j = 0; j < n * 4; j++) {
             if (i == j) continue;        
             for (int k = 0; k < n * 4; k++) {
                 if (j == k || i == k) continue;
                 pri[i][j] = pri[j][i] = min(pri[i][j], pri[i][k] + pri[j][k]);
             }
         }
     for (int i = 1; i <= 4; i++)
         for (int j = 1; j <= 4; j++)
             ans = min(ans, pri[s * 4 + i - 5][t * 4 + j - 5]);
     cout << fixed << setprecision(1) << ans;
     return 0;
 }

除了用多源的floyd算法还可以用单源的Dijkstra算法进行

double f(int m) {
double dis[500];
bool book[500] = {0};
fill(dis, dis + 500, inf);
for (int i = 0; i < 500; i++) dis[i] = inf;
dis[m] = 0;
for (int i = 1; i <= n * 4 - 1; i++) {
int minn = inf, u = -1;
for (int j = 1; j <= n * 4; j++) {
if (book[j] == false && dis[j] < minn) {
minn = dis[j];
u = j;
}
}
if (u == -1) break;
book[u] = true;
for (int k = 1; k <= n * 4; k++) {
if (e[u][k] < inf && dis[k] > e[u][k] + dis[u]) {
dis[k] = e[u][k] + dis[u];
}
}
}

ALGO-26. ⻨麦森数!


问题描述
形如2P-1的素数称为⻨麦森数,这时P⼀一定也是个素数。但反过来不不⼀一定,即如果P是个素数,2P-1不不⼀一
定也是素数。到1998年年底,⼈人们已找到了了37个⻨麦森数。最⼤大的⼀一个是P=3021377,它有909526位。
⻨麦森数有许多重要应⽤用,它与完全数密切相关。
任务:从⽂文件中输⼊入P(1000<P<3100000),计算2P-1的位数和最后500位数字(⽤用⼗十进制⾼高精度数
表示)
输⼊入格式
⽂文件中只包含⼀一个整数P(1000<P<3100000)
输出格式
第⼀一⾏行行:⼗十进制⾼高精度数2P-1的位数。
第2-11⾏行行:⼗十进制⾼高精度数2P-1的最后500位数字。(每⾏行行输出50位,共输出10⾏行行,不不⾜足500位时⾼高
位补0)
不不必验证2P-1与P是否为素数。
样例例输⼊入
1279
样例例输出
386
第⼀一⾏行行:⼗十进制⾼高精度数2P-1的位数。
第2-11⾏行行:⼗十进制⾼高精度数2P-1的最后500位数字。(每⾏行行输出50位,共输出10⾏行行,不不⾜足500位时⾼高
位补0)
不不必验证2P-1与P是否为素数。
样例例输⼊入
1279
样例例输出
386

ALGO-28. 星际交流


问题描述
⼈人类终于登上了了⽕火星的⼟土地并且⻅见到了了神秘的⽕火星⼈人。⼈人类和⽕火星⼈人都⽆无法理理解对⽅方的语⾔言,但是我
们的科学家发明了了⼀一种⽤用数字交流的⽅方法。这种交流⽅方法是这样 的,⾸首先,⽕火星⼈人把⼀一个⾮非常⼤大的数
字告诉⼈人类科学家,科学家破解这个数字的含义后,再把⼀一个很⼩小的数字加到这个⼤大数上⾯面,把结果
告诉⽕火星⼈人,作为⼈人类的回 答。
⽕火星⼈人⽤用⼀一种⾮非常简单的⽅方式来表示数字——掰⼿手指。⽕火星⼈人只有⼀一只⼿手,但这只⼿手上有成千上万的
⼿手指,这些⼿手指排成⼀一列列,分别编号为1,2,3……。⽕火星⼈人的任意两根⼿手指都能随意交换位置,他们
就是通过这⽅方法计数的。
⼀一个⽕火星⼈人⽤用⼀一个⼈人类的⼿手演示了了如何⽤用⼿手指计数。如果把五根⼿手指——拇指、⻝⾷食指、中指、⽆无名指
和⼩小指分别编号为1,2,3,4和5,当它们按正常顺序排列列 时,形成了了5位数12345,当你交换⽆无名指
和⼩小指的位置时,会形成5位数12354,当你把五个⼿手指的顺序完全颠倒时,会形成54321,在所有能
够形 成的120个5位数中,12345最⼩小,它表示1;12354第⼆二⼩小,它表示2;54321最⼤大,它表示
120。下表展示了了只有3根⼿手指时能够形成的6个 3位数和它们代表的数字:
三进制数
123
132
213
231
312
321
代表的数字
1
2
3
4
5
6
现在你有幸成为了了第⼀一个和⽕火星⼈人交流的地球⼈人。⼀一个⽕火星⼈人会让你看他的⼿手指,科学家会告诉你要
加上去的很⼩小的数。你的任务是,把⽕火星⼈人⽤用⼿手指表示的数与科 学家告诉你的数相加,并根据相加的
结果改变⽕火星⼈人⼿手指的排列列顺序。输⼊入数据保证这个结果不不会超出⽕火星⼈人⼿手指能表示的范围。
输⼊入格式
包括三⾏行行,第⼀一⾏行行有⼀一个正整数N,表示⽕火星⼈人⼿手指的数⽬目(1 <= N <= 10000)。第⼆二⾏行行是⼀一个正整
数M,表示要加上去的⼩小整数(1 <= M <= 100)。下⼀一⾏行行是1到N这N个整数的⼀一个排列列,⽤用空格隔
开,表示⽕火星⼈人⼿手指的排列列顺序。
输出格式
只有⼀一⾏行行,这⼀一⾏行行含有N个整数,表示改变后的⽕火星⼈人⼿手指的排列列顺序。每两个相邻的数中间⽤用⼀一个
空格分开,不不能有多余的空格。
样例例输⼊入
5
3
1 2 3 4 5
样例例输出
1 2 4 5 3
数据规模和约定
对于30%的数据,N<=15;
对于60%的数据,N<=50;
对于全部的数据,N<=10000;
思考:
这里用到了next_permutation函数,方便快熟的解决了问题

#include<iostream>
#include<algorithm>
using namespace std;

int N,M,a[10001];
int main(){
	cin>>N>>M;
	for(int i=0;i<N;i++)
		cin>>a[i];
	for(int i=0;i<M;i++)
		next_permutation(a,a+N);
	for(int i=0;i<N;i++)
		cout<<a[i]<<" ";
	 return 0;
	
}

ALGO-37. Hankson的趣味题

问题描述
Hanks 博⼠士是BT (Bio-Tech,⽣生物技术) 领域的知名专家,他的⼉儿⼦子名叫Hankson。现 在,刚刚放学
回家的Hankson 正在思考⼀一个有趣的问题。 今天在课堂上,⽼老老师讲解了了如何求两个正整数c1 和c2 的
最⼤大公约数和最⼩小公倍数。现 在Hankson 认为⾃自⼰己已经熟练地掌握了了这些知识,他开始思考⼀一个“求
公约数”和“求公 倍数”之类问题的“逆问题”,这个问题是这样的:已知正整数a0,a1,b0,b1,设某未知正
整 数x 满⾜足: 1. x 和a0 的最⼤大公约数是a1; 2. x 和b0 的最⼩小公倍数是b1。 Hankson 的“逆问
题”就是求出满⾜足条件的正整数x。但稍加思索之后,他发现这样的 x 并不不唯⼀一,甚⾄至可能不不存在。因
此他转⽽而开始考虑如何求解满⾜足条件的x 的个数。请你帮 助他编程求解这个问题。
输⼊入格式
输⼊入第⼀一⾏行行为⼀一个正整数n,表示有n 组输⼊入数据。
接下来的n ⾏行行每 ⾏行行⼀一组输⼊入数据,为四个正整数a0,a1,b0,b1,每两个整数之间⽤用⼀一个空格隔
开。输⼊入 数据保证a0 能被a1 整除,b1 能被b0 整除。
输出格式
输出共n ⾏行行。每组输⼊入数据的输出结果占⼀一⾏行行,为⼀一个整数。
对于每组数据:若不不存在这样的 x,请输出0; 若存在这样的 x,请输出满⾜足条件的x 的个数;
样例例输⼊入
2
41 1 96 288
95 1 37 1776
样例例输出
6
2
样例例说明
第⼀一组输⼊入数据,x 可以是9、18、36、72、144、288,共有6 个。
第⼆二组输⼊入数据,x 可以是48、1776,共有2 个。
数据规模和约定
对于 50%的数据,保证有1≤a0,a1,b0,b1≤10000 且n≤100。
对于 100%的数据,保证有1≤a0,a1,b0,b1≤2,000,000,000 且n≤2000。

#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
#include <cmath>
int gcd(int a, int b) {
if (b == 0) return a;
return gcd(b, a % b);
}
using namespace std;
int main() {
int a0, a1, b0, b1, k;
cin >> k;
while (k--) {
int ans = 0;
scanf("%d %d %d %d", &a0, &a1, &b0, &b1);
for (int i = 1; i * i <= b1; i++) {
if(b1 % i == 0){
int n = i;
if (gcd(a0, n) == a1 && b0 * n == b1 * gcd(b0, n))
ans++;
if(i != b1 / i) {
n = b1 / i;
if (gcd(a0, n) == a1 && b0 * n == b1 * gcd(b0, n))
ans++;
}
}
}
printf("%d\n",ans);
}
return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值