三月最后一周周报

这周是在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

V.JPG

病毒容易发生变异。某种病毒可以通过突变产生若干变异的毒株,而这些变异的病毒又可能被诱发突变产生第二代变异,如此继续不断变化。

现给定一些病毒之间的变异关系,要求你找出其中最长的一条变异链。

在此假设给出的变异都是由突变引起的,不考虑复杂的基因重组变异问题 —— 即每一种病毒都是由唯一的一种病毒突变而来,并且不存在循环变异的情况。

输入格式:

输入在第一行中给出一个正整数 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的人发红包的记录,格式如下:

KN1​P1​⋯NK​PK​

其中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;
}

 这道题就是考虑全六个方位应该就行,开三维和二维数组都可以,但是我这个代码会有五分过不了,可能是越界或者循环过多的情况,我还在修改。

这周的补题目前有这些,还有的有思路但是没改好,慢慢加油。

  • 51
    点赞
  • 47
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值