写两个关于OJ上的题目:
回文素数
描述
一个数如果从左往右读和从右往左读数字是相同的,则称这个数是回文数,如121,1221,15651都是回文数。给定位数n,找出所有既是回文数又是素数的n位十进制数。(注:不考虑超过整型数范围的情况)。
输入
位数n,其中1<=n<=9。
输出
第一行输出满足条件的素数个数。
第二行按照从小到大的顺序输出所有满足条件的素数,两个数之间用一个空格区分。
样例输入
1
样例输出
4
2 3 5 7
我觉得判断一个数是否为回文素数,可以进行两步判断,判断回文与判断素数,根据这两种判断顺序的不同可以有两种写法,我按的先回文后素数进行判断:不过。。。
wrong answer 九分:
下面是我的程序(写的比较麻烦,但是思路还是容易懂的,很多地方存在重复,可以进行合并从而减少很多代码行数(这里没有写到)):
(通过测试还发现偶数位的回文数似乎都不是素数。。。)
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;
int a[100001],b[100001];
bool fn(int &z);
int main()
{
int n,s=1,x=0,y=1;
cin>>n;
if(n==1)
{
cout<<"4"<<endl;
cout<<"2 3 5 7"<<endl;
}
if(n==2)
{
cout<<"0"<<endl;
}
if(n==3)
{
for(int i=10;i<=99;i++)
{
a[s]=i*10+i/10;
s++;
}
for(int j=1;j<=s-1;j++)
{
if(fn(a[j]))
{
x++;
b[y]=a[j];
y++;
}
}
cout<<x<<endl;
for(int i=1;i<=x;i++)
cout<<b[i]<<" ";
cout<<endl;
}
if(n==4)
{
for(int i=10;i<=99;i++)
{
a[s]=i*100+i%10*10+i/10;
s++;
}
for(int j=1;j<=s-1;j++)
{
if(fn(a[j]))
{
x++;
b[y]=a[j];
y++;
}
}
cout<<x<<endl;
for(int i=1;i<=x;i++)
cout<<b[i]<<" ";
cout<<endl;
}
if(n==5)
{
for(int i=100;i<=999;i++)
{
a[s]=i*100+i/10%10*10+i/100;
s++;
}
for(int j=1;j<=s-1;j++)
{
if(fn(a[j]))
{
x++;
b[y]=a[j];
y++;
}
}
cout<<x<<endl;
for(int i=1;i<=x;i++)
cout<<b[i]<<" ";
cout<<endl;
}
if(n==6)
{
for(int i=100;i<=999;i++)
{
a[s]=i*1000+i%10*100+i/10%10*10+i/100;
s++;
}
for(int j=1;j<=s-1;j++)
{
if(fn(a[j]))
{
x++;
b[y]=a[j];
y++;
}
}
cout<<x<<endl;
for(int i=1;i<=x;i++)
cout<<b[i]<<" ";
cout<<endl;
}
if(n==7)
{
for(int i=1000;i<=9999;i++)
{
a[s]=i*1000+i/10%10*100+i/100%10*10+i/1000;
s++;
}
for(int j=1;j<=s-1;j++)
{
if(fn(a[j]))
{
x++;
b[y]=a[j];
y++;
}
}
cout<<x<<endl;
for(int i=1;i<=x;i++)
cout<<b[i]<<" ";
cout<<endl;
}
if(n==8)
{
for(int i=1000;i<=9999;i++)
{
a[s]=i*10000+i%10*1000+i/10%10*100+i/100%10*10+i/1000;
s++;
}
for(int j=1;j<=s-1;j++)
{
if(fn(a[j]))
{
x++;
b[y]=a[j];
y++;
}
}
cout<<x<<endl;
for(int i=1;i<=x;i++)
cout<<b[i]<<" ";
cout<<endl;
}
if(n==9)
{
for(int i=10000;i<=99999;i++)
{
a[s]=i*10000+i/10%10*1000+i/100%10*100+i/1000%10*10+i/10000;
s++;
}
for(int j=1;j<=s-1;j++)
{
if(fn(a[j]))
{
x++;
b[y]=a[j];
y++;
}
}
cout<<x<<endl;
for(int i=1;i<=x;i++)
cout<<b[i]<<" ";
cout<<endl;
}
return 0;
}
bool fn(int &z)
{
for(int j=2;j<=sqrt(z);j++)
{
if(z%j==0)
{
return 0;
}
}
return 1;
}
接水问题
描述
学校里有一个水房,水房里一共装有 m 个龙头可供同学们打开水,每个龙头每秒钟的供水量相等,均为 1。
现在有 n 名同学准备接水,他们的初始接水顺序已经确定。将这些同学按接水顺序从 1 到 n 编号,i号同学的接水量为 wi。接水开始时,1 到 m 号同学各占一个水龙头,并同时打开水龙头接水。当其中某名同学 j 完成其接水量要求 wj后,下一名排队等候接水的同学 k 马上接替 j 同学的位置开始接水。这个换人的过程是瞬间完成的,且没有任何水的浪费。即 j 同学第 x 秒结束时完成接水,则 k 同学第 x+1 秒立刻开始接水。 若当前接水人数 n’不足 m,则只有 n’个龙头供水,其它 m-n’个龙头关闭。
现在给出 n 名同学的接水量,按照上述接水规则,问所有同学都接完水需要多少秒。
输入
第 1 行2 个整数 n 和 m,用一个空格隔开,分别表示接水人数和龙头个数。
第 2 行 n 个整数 w1、w2、……、wn,每两个整数之间用一个空格隔开,wi表示 i 号同学的接水量。
1 ≤ n ≤ 10000,1 ≤ m ≤ 100 且 m ≤ n;
1 ≤ wi ≤ 100。
输出
输出只有一行,1 个整数,表示接水所需的总时间。
样例输入
样例 #1:
5 3
4 4 1 2 1
样例 #2:
8 4
23 71 87 32 70 93 80 76
样例输出
样例 #1:
4
样例 #2:
163
提示
输入输出样例1解释:
第 1 秒,3 人接水。第 1秒结束时,1、2、3 号同学每人的已接水量为 1,3 号同学接完水,4 号同学接替 3 号同学开始接水。
第 2 秒,3 人接水。第 2 秒结束时,1、2 号同学每人的已接水量为 2,4 号同学的已接水量为 1。
第 3 秒,3 人接水。第 3 秒结束时,1、2 号同学每人的已接水量为 3,4 号同学的已接水量为 2。4号同学接完水,5 号同学接替 4 号同学开始接水。
第 4 秒,3 人接水。第 4 秒结束时,1、2 号同学每人的已接水量为 4,5 号同学的已接水量为 1。1、2、5 号同学接完水,即所有人完成接水。
总接水时间为 4 秒。
下面的代码是我的一位同学写的,不过当我问他时,他已经忘了。。。(写的有点乱,容易自己也不懂啊!haha~)(他没有使用绝大多数人会想到的贪心算法,我看完后,现在来分析一下这个代码。)
#include<iostream>
#include<cstdio>
#include<algorithm>
int r[10000]={0};
using namespace std;
int main()
{
int n,m,s=0,k=0,t,v,g=0;
cin>>n>>m;
v=m;
for(int a=0;a<n;a++)
cin>>r[a];
if(n<=m)
{
sort(r,r+n);
cout<<r[n-1]<<endl;
}
else
{
for(int a=0;a<n;a++)
s=s+r[a];
for(int a=0;a<=s;a++)
{
g=0;
for(int b=0;b<m;b++)
{
if(a==r[b])
{
r[b]=r[v]+a;
v++;
if(v>n)
r[b]=0;
}
if(r[b]==0)
g++;
}
t=a;
if(g==m)
break;
}
cout<<t<<endl;
}
return 0;}
分析:
一种是接水人数n<=水龙头个数m,此时不用多说接水时间就是接水时间最长的那位同学所用的时间;
另一种就是接水人数n>水龙头个数m时:
s=s+r[c];
s代表接水的总时长;
a==r[b];代表在第a秒时,0~m个水龙头接水时第b个同学完成接水,r[b]=r[v]+a;代表第m+1位同学到第b个水龙头开始接水,两位同学接水总时长r[b]=r[v]+a;此时自动跳转到下一位同学,v++;
if(g= =m)则代表所有同学都排到了水龙头,接到了水。
b号水龙头自动清空,则g++计数;if(g ==m)则所有水龙头都自动清空,即所有水龙头在接水的同学为空,即此时所有同学都接满了水,将t=a;break;输出时间t即可。