day20 adv 61\62\78\80\83\88

任务量:20

ADV-61. 矩阵乘⽅方!

问题描述
给定⼀一个矩阵A,⼀一个⾮非负整数b和⼀一个正整数m,求A的b次⽅方除m的余数。
其中⼀一个nxn的矩阵除m的余数得到的仍是⼀一个nxn的矩阵,这个矩阵的每⼀一个元素是原矩阵对应位置
上的数除m的余数。
要计算这个问题,可以将A连乘b次,每次都对m求余,但这种⽅方法特别慢,当b较⼤大时⽆无法使⽤用。下
⾯面给出⼀一种较快的算法(⽤用A^b表示A的b次⽅方):
若b=0,则A^b%m=I%m。其中I表示单位矩阵。
若b为偶数,则Ab%m=(A(b/2)%m)^2%m,即先把A乘b/2次⽅方对m求余,然后再平⽅方后对m求余。
若b为奇数,则Ab%m=(A(b-1)%m)a%m,即先求A乘b-1次⽅方对m求余,然后再乘A后对m求余。
这种⽅方法速度较快,请使⽤用这种⽅方法计算A^b%m,其中A是⼀一个2×2的矩阵,m不不⼤大于10000。
输⼊入格式
输⼊入第⼀一⾏行行包含两个整数b, m,第⼆二⾏行行和第三⾏行行每⾏行行两个整数,为矩阵A。
输出格式
输出两⾏行行,每⾏行行两个整数,表示A^b%m的值。
样例例输⼊入
2 2
1 1
0 1
样例例输出
1 0
0 1
思考:
由于矩阵只有2
2,所以使用快速幂巨额发更方便
分析:1.⽤用快速幂的解法递归下去即可
2.按照题⽬目测试数据,矩阵的0次⽅方,应该为全部数字为0, 矩阵的1次⽅方,矩阵不不变~

#include<iostream>
#include<cstring>
#include<vector>
using namespace std;
int m;
vector<int> mul(vector<int>a,vector<int>b){
	vector<int> ans(5);
	ans[1]=(a[1]*b[1]+a[2]*b[3])%m;
	ans[2]=(a[1]*b[2]+a[2]*b[4])%m;
	ans[3]=(a[3]*b[1]+a[4]*b[3])%m;
	ans[4]=(a[3]*b[2]+a[4]*b[4])%m;
	return ans;
	}
vector<int> f(vector<int> v, int b) {
	vector<int> minn(5),nulln(5);
	minn[1] = minn[4] = 1;
		if (b == 0) {
		return mul(minn, nulln);
		} else if (b == 1) {
		return mul(v, minn);
		}else if(b%2==0){
			vector<int >t(5);
			t=f(v,b/2);
			return mul(t,t);
		}else{
			vector<int >t(5);
			t=f(v,b-1);
			return mul(t,v);
		}
} 
int main(){
	int b,m;
	cin>>b>>m;
	vector<int >v(5),ans;
	cin>>v[1]>>v[2]>>v[3]>>v[4];
	ans=f(v,b);
	cout<<ans[1]<<" "<<ans[2]<<endl<<ans[3]<<" "<<ans[4];
	return 0;
}

ADV-62. 夺宝奇兵

[题⽬目描述]
  在⼀一座⼭山上,有很多很多珠宝,它们散落在⼭山底通往⼭山顶的每条道路路上,不不同道路路上的珠宝的数⽬目也
各不不相同.下图为⼀一张藏宝地图:
  7
  3 8
  8 1 0
  2 7 4 4
  4 5 2 6 5
  ”夺宝奇兵”从⼭山下出发,到达⼭山顶,如何选路路才能得到最多的珠宝呢?在上图所示例例⼦子中,按照5->7-

8->3->7的顺序,将得到最⼤大值30
[输⼊入]
  第⼀一⾏行行正整数N(100>=N>1),表示⼭山的⾼高度
  接下来有N⾏行行⾮非负整数,第i⾏行行有i个整数(1<=i<=N),表示⼭山的第i层上从左到右每条路路上的珠宝数⽬目
[输出]
  ⼀一个整数,表示从⼭山底到⼭山顶的所能得到的珠宝的最⼤大数⽬目.
[样例例输⼊入]
5
7
3 8
8 1 0
2 7 4 4
4 5 2 6 5
[样例例输出]
30
思考:
经典动态规划之数学三角形问题(选择往下走或者往右走)
并且他只能往下走或者往右走
所以最左边的一列只能是s[i][j]+=s[i-1][jj]
最右边s[i][j]+=s[i-1][j-1];中间的列s[i][j]=max(s[i][j]+s[i-1][j-1],s[i][j]+s[i-1][j]);
所以只需要看最后一列谁最大

#include<iostream>
using namespace std;
int main(){
	int n;
	cin>>n;
	int s[n][n];
	for(int i=0;i<n;i++){
		for(int j=0;j<=i;j++)
			cin>>s[i][j];
	}
	for(int i=1;i<n;i++){
		for(int j=0;j<=i;j++){
			if(j==0)
				s[i][j]+=s[i-1][j];
			else if(j==i)
				s[i][j]+=s[i-1][j-1];
			else{
				s[i][j]=max(s[i][j]+s[i-1][j-1],s[i][j]+s[i-1][j]);
			}
		}
	}
	int max=s[n-1][0];
	for(int j=1;j<n;j++)
	{
		if(max<s[n-1][j])
			max=s[n-1][j];
		}	
	cout<<max;
	return 0;
}

ADV-78. 最⻓长单词

编写⼀一个函数,输⼊入⼀一⾏行行字符,将此字符串串中最⻓长的单词输出。
  输⼊入仅⼀一⾏行行,多个单词,每个单词间⽤用⼀一个空格隔开。单词仅由⼩小写字⺟母组成。所有单词的⻓长度
和不不超过100000。如有多个最⻓长单词,输出最先出现的。
样例例输⼊入
I am a student
样例例输出
student

#include <iostream>
using namespace std;
int main() {
string s;
string temp;
int mmax = 0;
while(cin >> temp) {
int len = temp.length();
if(mmax < len) {
mmax = len;
s = temp;
}
}
cout << s;
return 0;
}

ADV-80. 选最⼤大数

输⼊入3个整数a、b、c,(数的范围是[1,10000])输出其中最⼤大的数。(⽤用指针实现)
样例例输⼊入
2 5 1
样例例输出
5
思考:
这种指针的方式注意一下

#include <iostream>
using namespace std;
int main() {
int a, b, c;
cin >> a >> b >> c;
int *p = a;
if(*p < b)
p = &b;
if(*p < c)
p = &c;
return 0;
}

ADV-83. 寻找三位数!!

问题描述
  将1,2,…,9共9个数分成三组,分别组成三个三位数,且使这三个三位数构成
  1:2:3的⽐比例例,试求出所有满⾜足条件的三个三位数。
  例例如:三个三位数192,384,576满⾜足以上条件。
  输⼊入格式
  ⽆无输⼊入⽂文件
输出格式
  输出每⾏行行有三个数,为满⾜足题设三位数。各⾏行行为满⾜足要求的不不同解。
分析:先确定第⼀一个数字,然后判断这个数字的两倍数和三倍数是否满⾜足条件~⽤用book数组标记当前
数字是否已经出现过~
思考:我只想表达这也太乱了吧

#include <iostream>
using namespace std;
bool judge(int i, int j, int k) {
int book[10] = {0};
book[0] = 1;
if(i == j || j == k || i == k)
return false;
book[i] = 1, book[j] = 1, book[k] = 1;
int one = i * 100 + j * 10 + k;
int two = 2 * one;
int three = 3 * one;
if(two >= 666 || three >=987)
return false;
if(book[two/100] == 1)
return false;
else
book[two/100] = 1;
if(book[two%100/10] == 1)
return false;
else
book[two%100/10] = 1;
if(book[two%10] == 1)
return false;
else
book[two%10] = 1;
if(book[three/100] == 1)
return false;
else
book[three/100] = 1;
if(book[three%100/10] == 1)
return false;
else
book[three%100/10] = 1;
if(book[three%10] == 1)
return false;
else
return true;
}
int main() {
for(int i = 1; i <= 3; i++) {
for(int j = 1; j <= 9; j++) {
for(int k = 1; k <= 9; k++) {
if(judge(i, j, k) == true) {
int one = i * 100 + j * 10 + k;
cout << one << " " << one * 2 << " " << one * 3 <<
endl;
}
}
}
}
return 0;
}

ADV-88. 输出正反三⻆角形

使⽤用循环结构打印下述图形,打印⾏行行数n由⽤用户输⼊入。图中每⾏行行事实上包括两部分,中间间隔空格字
符数m也由⽤用户输⼊入。
样例例输⼊入n,m:
样例例输⼊入n,m:
5 4
样例例输出:






思考:这个不能用字符串做,太麻烦了。一个一个输出会比较好

#include <iostream>
using namespace std;
int main() {
int n, m;
cin >> n >> m;
for(int i = 1; i <= n; i++) {
for(int j = 1; j <= n - i; j++)
cout << " ";
for(int j = 1; j <= 2 * i - 1; j++)
cout << "*";
for(int j = 1; j <= m; j++)
cout << " ";
for(int j = 1; j <= 2 * (n - i + 1) - 1; j++)
cout << "*";
cout << endl;
}
return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值