这周是在PTA上拉的题,然后这些补题是在比赛时感觉能做,但是总是有所欠缺
7-8 连续因子
分数 20
一个正整数 N 的因子中可能存在若干连续的数字。例如 630 可以分解为 3×5×6×7,其中 5、6、7 就是 3 个连续的数字。给定任一正整数 N,要求编写程序求出最长连续因子的个数,并输出最小的连续因子序列。
输入格式:
输入在一行中给出一个正整数 N(1<N<231)。
输出格式:
首先在第 1 行输出最长连续因子的个数;然后在第 2 行中按 因子1*因子2*……*因子k
的格式输出最小的连续因子序列,其中因子按递增顺序输出,1 不算在内。
输入样例:
630
输出样例:
3
5*6*7
鸣谢用户 漏穿雪 补充数据!
代码长度限制
16 KB
时间限制
400 ms
内存限制
64 MB
#include<bits/stdc++.h>
using namespace std;
int main(){
long long n,x;
cin>>n;
int g=0,maxg=0,start=0;
for(int i=2;i<=sqrt(n);i++){
x=n;
g=0;
int j=i;
while(x%j==0){
x/=j;
j++;
g++;
}
if(g>maxg){
maxg=g;
start=i;
}
}
if(maxg){
cout<<maxg<<endl;
for(int i=0;i<maxg;i++){
cout<<start+i;
if(i!=maxg-1) printf("*");
}
}
else cout<<"1"<<endl<<n;
return 0;
}
这道题在比赛时的想法是每个都找到,再在数组中选择,但是后面认真读题后,只需要直接找到最长的那组,然后两个问题就都解决了,我的那种想法会超时。
7-9 哈利·波特的考试
分数 25
哈利·波特要考试了,他需要你的帮助。这门课学的是用魔咒将一种动物变成另一种动物的本事。例如将猫变成老鼠的魔咒是haha,将老鼠变成鱼的魔咒是hehe等等。反方向变化的魔咒就是简单地将原来的魔咒倒过来念,例如ahah可以将老鼠变成猫。另外,如果想把猫变成鱼,可以通过念一个直接魔咒lalala,也可以将猫变老鼠、老鼠变鱼的魔咒连起来念:hahahehe。
现在哈利·波特的手里有一本教材,里面列出了所有的变形魔咒和能变的动物。老师允许他自己带一只动物去考场,要考察他把这只动物变成任意一只指定动物的本事。于是他来问你:带什么动物去可以让最难变的那种动物(即该动物变为哈利·波特自己带去的动物所需要的魔咒最长)需要的魔咒最短?例如:如果只有猫、鼠、鱼,则显然哈利·波特应该带鼠去,因为鼠变成另外两种动物都只需要念4个字符;而如果带猫去,则至少需要念6个字符才能把猫变成鱼;同理,带鱼去也不是最好的选择。
输入格式:
输入说明:输入第1行给出两个正整数N (≤100)和M,其中N是考试涉及的动物总数,M是用于直接变形的魔咒条数。为简单起见,我们将动物按1~N编号。随后M行,每行给出了3个正整数,分别是两种动物的编号、以及它们之间变形需要的魔咒的长度(≤100),数字之间用空格分隔。
输出格式:
输出哈利·波特应该带去考场的动物的编号、以及最长的变形魔咒的长度,中间以空格分隔。如果只带1只动物是不可能完成所有变形要求的,则输出0。如果有若干只动物都可以备选,则输出编号最小的那只。
输入样例:
6 11
3 4 70
1 2 1
5 4 50
2 6 50
5 6 60
1 3 70
4 6 60
3 6 80
5 1 100
2 4 60
5 2 80
输出样例:
4 70
代码长度限制
16 KB
时间限制
400 ms
内存限制
64 MB
#include<bits/stdc++.h>
using namespace std;
#define d 10000000
int p[105][105];
int n,m;
int animal=d;
int id=0;
void findmin(){
for(int j=1;j<=n;j++){
for(int i=1;i<=n;i++){
for(int k=1;k<=n;k++){
if(i!=j&&i!=k&&(p[i][j]+p[j][k]<p[i][k])){
p[i][k]=p[i][j]+p[j][k];
}
}
}
}
for(int i=1;i<=n;i++){
int dismax=-1;
for(int j=1;j<=n;j++){
if(i!=j&&p[i][j]>dismax){
dismax=p[i][j];
}
}
if(dismax==d){
printf("0");
return;
}
if(dismax<animal){
animal=dismax;
id=i;
}
}
cout<<id<<" "<<animal;
}
int main(){
cin>>n>>m;
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
p[i][j]=d;
p[j][i]=d;
}
}
int k1,k2,k3;
for(int i=0;i<m;i++){
cin>>k1>>k2>>k3;
p[k1][k2]=k3;
p[k2][k1]=k3;
}
findmin();
return 0;
}
这道题就是比赛的时候对于图论和最小路径的问题并不熟悉,然后还有其中的Floyd算法,先定中点和先定起点都是存在问题的,通过这道题会有所理解。
7-11 病毒溯源
分数 25
病毒容易发生变异。某种病毒可以通过突变产生若干变异的毒株,而这些变异的病毒又可能被诱发突变产生第二代变异,如此继续不断变化。
现给定一些病毒之间的变异关系,要求你找出其中最长的一条变异链。
在此假设给出的变异都是由突变引起的,不考虑复杂的基因重组变异问题 —— 即每一种病毒都是由唯一的一种病毒突变而来,并且不存在循环变异的情况。
输入格式:
输入在第一行中给出一个正整数 N(≤104),即病毒种类的总数。于是我们将所有病毒从 0 到 N−1 进行编号。
随后 N 行,每行按以下格式描述一种病毒的变异情况:
k 变异株1 …… 变异株k
其中 k
是该病毒产生的变异毒株的种类数,后面跟着每种变异株的编号。第 i 行对应编号为 i 的病毒(0≤i<N)。题目保证病毒源头有且仅有一个。
输出格式:
首先输出从源头开始最长变异链的长度。
在第二行中输出从源头开始最长的一条变异链,编号间以 1 个空格分隔,行首尾不得有多余空格。如果最长链不唯一,则输出最小序列。
注:我们称序列 { a1,⋯,an } 比序列 { b1,⋯,bn } “小”,如果存在 1≤k≤n 满足 ai=bi 对所有 i<k 成立,且 ak<bk。
输入样例:
10
3 6 4 8
0
0
0
2 5 9
0
1 7
1 2
0
2 3 1
输出样例:
4
0 4 9 1
代码长度限制
16 KB
时间限制
400 ms
内存限制
64 MB
栈限制
#include<bits/stdc++.h>
using namespace std;
int yt[10005];//源头
vector<int> v[10005],maxa,maxx;//当前的路径,最长的路径
void dfs(int x){//寻找病毒源头
if(maxa.size()>maxx.size()) maxx=maxa;
for(int j=0;j<v[x].size();j++){
maxa.push_back(v[x][j]);
dfs(v[x][j]);
maxa.pop_back();//回溯
}
}
int main(){
int n,k,a;
cin>>n;
for(int i=0;i<n;i++){
cin>>k;
while(k--){
cin>>a;
yt[a]=1;
v[i].push_back(a);
}
if(v[i].size()){
sort(v[i].begin(),v[i].end());//为了找最小序列
}
}
for(int i=0;i<n;i++){
if(!yt[i]){
maxa.push_back(i);
dfs(i);
break;
}
}
cout<<maxx.size()<<endl;
for(int i=0;i<maxx.size();i++){
if(i) cout<<" ";
cout<<maxx[i];
}
return 0;
}
这道题是看题解看会的,关键就是找最小序以及dfs的部分。
7-9 抢红包
分数 25
没有人没抢过红包吧…… 这里给出N个人之间互相发红包、抢红包的记录,请你统计一下他们抢红包的收获。
输入格式:
输入第一行给出一个正整数N(≤104),即参与发红包和抢红包的总人数,则这些人从1到N编号。随后N行,第i行给出编号为i的人发红包的记录,格式如下:
KN1P1⋯NKPK
其中K(0≤K≤20)是发出去的红包个数,Ni是抢到红包的人的编号,Pi(>0)是其抢到的红包金额(以分为单位)。注意:对于同一个人发出的红包,每人最多只能抢1次,不能重复抢。
输出格式:
按照收入金额从高到低的递减顺序输出每个人的编号和收入金额(以元为单位,输出小数点后2位)。每个人的信息占一行,两数字间有1个空格。如果收入金额有并列,则按抢到红包的个数递减输出;如果还有并列,则按个人编号递增输出。
输入样例:
10
3 2 22 10 58 8 125
5 1 345 3 211 5 233 7 13 8 101
1 7 8800
2 1 1000 2 1000
2 4 250 10 320
6 5 11 9 22 8 33 7 44 10 55 4 2
1 3 8800
2 1 23 2 123
1 8 250
4 2 121 4 516 7 112 9 10
输出样例:
1 11.63
2 3.63
8 3.63
3 2.11
7 1.69
6 -1.67
9 -2.18
10 -3.26
5 -3.26
4 -12.32
#include<bits/stdc++.h>
using namespace std;
struct QH{
int id;//编号
int dq;//得到的钱数(以分为单位)
int fq;//发出的钱数
int hb;//抢到的红包个数
double zq;//最后的实际亏损
} qhr[10005];
bool cmp(QH a,QH b){
if(a.zq!=b.zq) return a.zq>b.zq;
else{
if(a.hb!=b.hb){
return a.hb>b.hb;
}
else{
return a.id<b.id;
}
}
}
int main()
{
int n;
cin>>n;
for(int i=1;i<=n;i++){
qhr[i].id=i;
qhr[i].dq=0;
qhr[i].fq=0;
qhr[i].hb=0;
qhr[i].zq=0;
}
for(int i=1;i<=n;i++){
int k;
cin>>k;
for(int j=0;j<k;j++){
int nid,q;
cin>>nid>>q;
qhr[nid].dq+=q;
qhr[i].fq+=q;
qhr[nid].hb++;
}
}
for(int i=1;i<=n;i++){
qhr[i].zq=1.0*(qhr[i].dq-qhr[i].fq)/100;
}
sort(qhr+1,qhr+1+n,cmp);
for(int i=1;i<=n;i++){
printf("%d %.2lf\n",qhr[i].id,qhr[i].zq);
}
return 0;
}
这道题是比赛的时候脑子里一直想着用pair(脑子出问题),但是不合适,直接用结构体多用几个变量就好了,一个正常的模拟题。
7-13 肿瘤诊断
分数 30
在诊断肿瘤疾病时,计算肿瘤体积是很重要的一环。给定病灶扫描切片中标注出的疑似肿瘤区域,请你计算肿瘤的体积。
输入格式:
输入第一行给出4个正整数:M、N、L、T,其中M和N是每张切片的尺寸(即每张切片是一个M×N的像素矩阵。最大分辨率是1286×128);L(≤60)是切片的张数;T是一个整数阈值(若疑似肿瘤的连通体体积小于T,则该小块忽略不计)。
最后给出L张切片。每张用一个由0和1组成的M×N的矩阵表示,其中1表示疑似肿瘤的像素,0表示正常像素。由于切片厚度可以认为是一个常数,于是我们只要数连通体中1的个数就可以得到体积了。麻烦的是,可能存在多个肿瘤,这时我们只统计那些体积不小于T的。两个像素被认为是“连通的”,如果它们有一个共同的切面,如下图所示,所有6个红色的像素都与蓝色的像素连通。
输出格式:
在一行中输出肿瘤的总体积。
输入样例:
3 4 5 2
1 1 1 1
1 1 1 1
1 1 1 1
0 0 1 1
0 0 1 1
0 0 1 1
1 0 1 1
0 1 0 0
0 0 0 0
1 0 1 1
0 0 0 0
0 0 0 0
0 0 0 1
0 0 0 1
1 0 0 0
输出样例:
26
#include<bits/stdc++.h>
using namespace std;
int a[75][1500][130];
int dfs(int k,int i,int j){
int count=0;
if(a[k][i][j]==1){
a[k][i][j]=2;
count++;
}
if(a[k][i+1][j]==1){
count+=dfs(k,i+1,j);
a[k][i+1][j]=2;
}
if(a[k][i-1][j]==1){
count+=dfs(k,i-1,j);
a[k][i-1][j]=2;
}
if(a[k][i][j-1]==1){
count+=dfs(k,i,j-1);
a[k][i][j-1]=2;
}
if(a[k][i][j+1]==1){
count+=dfs(k,i,j+1);
a[k][i][j+1]=2;
}
if(a[k+1][i][j]==1){
count+=dfs(k+1,i,j);
a[k+1][i][j]=2;
}
if(a[k-1][i][j]==1){
count+=dfs(k-1,i,j);
a[k-1][i][j]=2;
}
return count;
}
int main(){
int m,n,l,t;
int sum=0;
cin>>m>>n>>l>>t;
for(int k=1;k<=l;k++){
for(int i=1;i<=m;i++){
for(int j=1;j<=n;j++){
cin>>a[k][i][j];
}
}
}
for(int k=1;k<=l;k++){
for(int i=1;i<=m;i++){
for(int j=1;j<=n;j++){
int z=dfs(k,i,j);
if(z>=t) sum+=z;
}
}
}
printf("%d",sum);
return 0;
}
这道题就是考虑全六个方位应该就行,开三维和二维数组都可以,但是我这个代码会有五分过不了,可能是越界或者循环过多的情况,我还在修改。
这周的补题目前有这些,还有的有思路但是没改好,慢慢加油。