问题 A: XP的素数
题目描述
XP最近对素数很痴迷,特别是那些特殊的素数,其中有一类素数被称为孪生素数。其定义如下:如果一个数k是素数,k+2也是素数,那么k和k+2成为一对孪生素数。请计算一个给定区间m和n(0<m<n)中孪生素数对的个数。
输入
单组输入数据
m n
(0<m<n<1000)
输出
请输出一行结果:区间[m,n]中孪生素数对的个数
#include<bits/stdc++.h>
#define ll long long
const int N=1005;
#include<bits/stdc++.h>
using namespace std;
int coun;
int s;
int a[N];
int prime(int n){//判断素数
if(n==1)//注意输入的数据,如果为1则不是素数
return 0;
for(int j=2;j<=sqrt(n);j++){//调用平方根函数,减少时间
if(n%j==0){
return 0;
}
}
return 1;
}
int main(){
int m,n;
int cou=0;
cin>>m>>n;
for(int i=m;i+2<=n;i++){
if(prime(i)&&prime(i+2))
cou++;
}
cout<<cou<<endl;
return 0;
}
问题 B: XP的三角形
题目描述
XP最喜欢的图形是三角形,最近他在研究直角三角形,他想到这么一个问题,如果三边长{a,b,c}均为整数的直角三角形周长为p,(a<=b<=c)当p = 120时,恰好存在三个不同的解:{a=20,b=48,c=52}, {a=24,b=45,c=51}, {a=30,b=40,c=50}。现在给定一个p求不同的解的个数。(p<=1000)
输入
单组输入数据
p
输出
输出一行结果
#include<bits/stdc++.h>
#define ll long long
const int N=1005;
#include<bits/stdc++.h>
using namespace std;
int coun;
int s;
int a[N];
int main(){
int p,ct=0;
cin>>p;
for(int i=1;i<p;i++){
for(int j=i;j<p;j++){
if((i*i+j*j)==(p-i-j)*(p-i-j)){
ct++;
}
}
}
cout<<ct<<endl;
return 0;
}
问题 C: XP的点滴
题目描述
XP一不留神感冒了,于是跑到校医院打点滴。打点滴真是无聊啊,他看到盐水一滴一滴地滴下来,突然想到一个问题:如果盐水有规律地滴下,先滴一滴,停一下;然后滴二滴,停一下;再滴三滴,停一下…,假设这瓶盐水一共有n毫升,每一滴是y毫升,每一滴需要的时间是一秒(假设最后一滴不到y毫升,需花费的时间也算一秒),停一下的时间也是一秒。请问XP多久能挂完这瓶盐水呢?
输入
单组输入数据
n y (0<n,y<=1000)
输出
输出一行结果
#include<bits/stdc++.h>
#define ll long long
const int N=1005;
#include<bits/stdc++.h>
using namespace std;
int coun;
int s;
int a[N];
//这里是每滴一滴就是1秒
int main(){
int n,y,sm=0;
int ct=0;
cin>>n>>y;
int tim = ceil(n*1.0/y);//向上取整,比如ceil(1.2)=2,用来解决问题中最后一滴,剩余而不足Y毫升
if(tim==1){//如果不足Y毫升就输出,结束程序
cout<<tim<<endl;
return 0;
}else{
int t=tim;
int i=1;//用来代表每次滴下的滴数
ct=1;//用来计数每次间隔停一下的时间
while(t){
t-=i;//减去滴数
i+=1;
if(t-i<=0)
break;
ct++;
}
}
cout<<tim+ct<<endl;//输出每滴时间+间隔停止时间
return 0;
}
问题 D: 月饼
题目描述
月饼是中国人在中秋佳节时吃的一种传统食品,不同地区有许多不同风味的月饼。现给定所有种类月饼的库存量、总售价、以及市场的最大需求量,请你计算可以获得的最大收益是多少。
注意:销售时允许取出一部分库存。样例给出的情形是这样的:假如我们有3种月饼,其库存量分别为18、15、10万吨,总售价分别为75、72、45亿元。如果市场的最大需求量只有20万吨,那么我们最大收益策略应该是卖出全部15万吨第2种月饼、以及5万吨第3种月饼,获得 72 + 45/2 = 94.5(亿元)。
输入
每个输入包含1个测试用例。每个测试用例先给出一个不超过1000的正整数N表示月饼的种类数、以及不超过500(以万吨为单位)的正整数D表示市场最大需求量。随后一行给出N个正实数表示每种月饼的库存量(以万吨为单位);最后一行给出N个正实数表示每种月饼的总售价(以亿元为单位)。数字间以空格分隔。
输出
对每组测试用例,在一行中输出最大收益,以亿元为单位并精确到小数点后2位。
千万别信这个题目所说的是什么整数,还有什么东西,俺试过自己按照部分背包的思想写过的代码,都没过,86%的错误,还在其他博客找过代码,都没过,在下面是AC代码,有点莫名其妙的坑,莫名其妙,俺菜的抠脚
#include<bits/stdc++.h>
using namespace std;
typedef struct {
double kucu=0;//库存
double shoujia=0;//售价
double price=0;//单位库存的价钱
}Pie;
Pie pie[1005];
bool cmp(Pie a,Pie b)//排序比较函数,降序
{
return a.price>b.price;
}
int main()
{
int n=0;
double xuqiu=0;
while(scanf("%d%lf",&n,&xuqiu)!=EOF)
{
double money=0;
double sum=0,maxn=0;
for(int i=0;i<n;i++)
{
scanf("%lf",&pie[i].kucu);
}
for(int i=0;i<n;i++)
{
scanf("%lf",&pie[i].shoujia);
pie[i].price=pie[i].shoujia/pie[i].kucu;
}
sort(pie,pie+n,cmp);
for(int i=0;i<n;i++)
{
double temp=xuqiu-pie[i].kucu;//用来存储剩余的库存
if(temp>0.0)
{
xuqiu=temp;
money=money+pie[i].shoujia;
}
else//当不足需求时,装一部分
{
money=money+xuqiu*pie[i].price;
printf("%.2lf\n",money);
return 0;
}
}
}
return 0;
}
问题 E: 今年暑假不AC
题目描述
“今年暑假不AC?”
“是的。”
“那你干什么呢?”
“看世界杯呀,笨蛋!”
“@#$%^&*%…”
确实如此,世界杯来了,球迷的节日也来了,估计很多ACMer也会抛开电脑,奔向电视了。
作为球迷,一定想看尽量多的完整的比赛,当然,作为新时代的好青年,你一定还会看一些其它的节目,比如新闻联播(永远不要忘记关心国家大事)、非常6+7、超级女生,以及王小丫的《开心辞典》等等,假设你已经知道了所有你喜欢看的电视节目的转播时间表,你会合理安排吗?(目标是能看尽量多的完整节目)
输入
输入数据包含多个测试实例,每个测试实例的第一行只有一个整数n(n<=100),表示你喜欢看的节目的总数,然后是n行数据,每行包括两个数据Ti_s,Ti_e (1<=i<=n),分别表示第i个节目的开始和结束时间,为了简化问题,每个时间都用一个正整数表示。n=0表示输入结束,不做处理。
输出
对于每个测试实例,输出能完整看到的电视节目的个数,每个测试实例的输出占一行。
#include<bits/stdc++.h>
using namespace std;
typedef struct {
int stime;//用来存放开始时间
int etime;//用来存放结束时间
}Tme;
Tme tme[1005];
bool cmp(Tme& a,Tme& b)//用来排序,将结束时间升序,越早结束的能够为后面让出更多时间观看更多节目
{
return a.etime<b.etime;
}
int main()
{
int n;
while(~scanf("%d",&n)&&n)
{
int last=1;//用来存放节目,因为求得是节目个数,没有别的约束,是从第一个开始的
for(int i=0;i<n;i++){
cin>>tme[i].stime>>tme[i].etime;
}
sort(tme,tme+n,cmp);
int temp=tme[0].etime;//用来表示每个可以观看的当前结束时间
for(int j=1;j<n;j++){
if(tme[j].stime>=temp){//只要结束时间小于等于下一个节目的开始时间,就可以进行观看,而且由于结束时间排过序,结果是最优的
temp=tme[j].etime;
last++;
}
}
cout<<last<<endl;
}
return 0;
}
问题 F: 最优装载
题目描述
使用贪心算法求解最优装载问题。
输入
每组输入包括两部分,
第一行包括集装箱个数n,以及船的装载量C。
接下来n行每行则输入集装箱编号以及其重量。
输出
输出包括两行,第一行为最多可装载的集装箱数量 。
第二行则为最优装载方案对应的所有集装箱编号(用空格隔开) 。
#include<bits/stdc++.h>
using namespace std;
typedef struct {
int id;//用来存放每个箱子的ID,因为排序过程会打乱,需要这个进行记录
double w;//用来存放重量
}Box;
Box boxs[1005];
int x[1005];//用来记录哪个箱子被相中
bool cmp(Box& a,Box& b)
{
return a.w<b.w;//升序,达到装的最多的箱子
}
int main()
{
int n;
double all;
while(~scanf("%d %lf",&n,&all))
{
int last=0;
memset(x,0,sizeof(x));
for(int i=1;i<=n;i++){
cin>>boxs[i].id>>boxs[i].w;
}
sort(boxs+1,boxs+n+1,cmp);//因为是从1开始记录的,所以都要加一
for(int j=1;j<=n;j++){
double temp=all-boxs[j].w;//用来判断船的容量是否装满
if(temp>=0.0){
all=temp;//更新船的容量
last++;
x[j]=1;//记录箱子被装载
}
}
cout<<last<<endl;
for(int k=1;k<=n;k++){//用来输出被装载的箱子,1代表被装载,则输出
if(x[k]){
cout<<boxs[k].id<<" ";
}
}
cout<<endl;
}
return 0;
}
问题 G: 最小生成树(Prim)
题目描述
使用Prim算法求图的最小生成树(MST)
输入
每组数据分为两个部分,第一部分为图的点数n,和边数m,
第二部分为m行,每一行输入三个数字,前两个为两个顶点的编号,第三个为边权重。
输出
最小生成树,输出时按照边的两个端点的升序输出。(先看左端点,再看右端点,端点不换位置)
#include<bits/stdc++.h>
using namespace std;
const int N=1005;
int INF=100000;
//运用贪心思想,在每一步求最优,得到结果是最优的
typedef struct{//用来保存符合要求的答案
int x;
int y;
int v;
} Node;
typedef struct{//用来保存原始边的信息
int x;
int y;
int v;
}M;
M mp[N];
bool cmp(Node& a,Node&b){//用来排序参数
if(a.x==b.x)
return a.y<b.y;
return a.x<b.x;
}
Node node[N];
int main()
{
int n,m;
int e1,e2;
int v;
while(~scanf("%d %d",&n,&m)){
int s[n+1];
int G[n+1][n+1];
int leng[n+1];
int used[n+1];
for(int ii=0;ii<n;ii++){//初始化图
for(int jj=0;jj<n;jj++){
G[ii][jj]=INF;
}
}
int flag=0;
for(int k=0;k<m;k++){//存入数据,再保存边的信息
cin>>e1>>e2>>v;
G[e1][e2]=G[e2][e1]=v;
mp[k].x=e1;
mp[k].y=e2;
mp[k].v=v;
}
for(int i=0;i<n;i++){//初始化第一个带你到其他点的权值
leng[i]=G[0][i];
s[i]=0;
used[i]=0;
}
used[0]=1;
for(int i=1;i<n;i++){
int j=0;
for(int k=0;k<n;k++){//选出这一点到其他点权值最少的点
// cout<<"leng"<<leng[j]<<" ";
if((!used[k])&&leng[k]<leng[j]){
j=k;
// cout<<"test:"<<j<<" "<<leng[k]<<" ";
}
}
// cout<<endl;
node[flag].x=s[j];//用来保存符合题意的答案
node[flag].y=j;
node[flag].v=leng[j];
flag++;
used[j]=1;
for(int k=1;k<n;k++){//用来更新这一点到其他点的权值
if((!used[k])&&G[j][k]<leng[k]){
leng[k]=G[j][k];
s[k]=j;
// cout<<"test2:"<<leng[k]<<" "<<s[k]<<" ";
}
}
// cout<<endl;
}
sort(node,node+flag,cmp);//按照题意用来排序
for(int k=0;k<flag;k++){
int temp=0;//用来判断是否与输入是否一样
for(int i=0;i<n;i++){
if( node[k].x==mp[i].x&&node[k].y==mp[i].y){
// printf("testppp:%d %d %d\n",node[k].x,node[k].y,node[k].v);
temp=1;
break;
}
}
if(temp){//如果存在则按照正常输出,反之,则反向输出
printf("%d %d %d\n",node[k].x,node[k].y,node[k].v);
}else{
printf("%d %d %d\n",node[k].y,node[k].x,node[k].v);
}
}
}
return 0;
}
问题 H: XP的小视频
题目描述
XP的表哥为他推荐了一些学习计算机编程的小视频,这些视频的播放时间长短不完全相同。现在给定一段时间,你能告诉XP他最多可以看多少个视频吗?每个视频的播放时间和给定的总时间均用分钟为单位。
输入
单组输入数据
第一行为m n
m为给定时间长度(分钟)(0<n,m<=1000)
n表示视频个数
接下来是n个整数代表每个视频的播放时间(每个视频播放时间为不超过1000的正整数)
输出
输出一个整数代表XP最多可以看的视频数。
#include<bits/stdc++.h>
using namespace std;
int x[1005];
int main()
{//运用贪心思想,将时长最短的视频先看,最后会看到更多
int n;
int all;
scanf("%d %d",&all,&n);
int last=0;
memset(x,0,sizeof(x));
for(int i=1;i<=n;i++){
cin>>x[i];
}
sort(x+1,x+n+1);
for(int j=1;j<=n;j++){
double temp=all-x[j];
if(temp>=0.0){
all=temp;
last++;
}
}
cout<<last<<endl;
return 0;
}