Ignatius and the Princess IV
来自 HDU - 1029
题面:
给你n个数字,请你找出出现至少(n+1)/2次的数字。
输入
本题包含多组数据,请处理到EOF:
每组数据包含两行。
第一行一个数字N(1<=N<=999999) ,保证N为奇数。
第二行为N个用空格隔开的整数。
输出
对于每组数据,输出一行,表示要求找到的那个数
样例输入
5
1 3 2 3 3
11
1 1 1 1 1 5 5 5 5 5 5
7
1 1 1 1 1 1 1
样例输出
3
5
1
看到这里 ,相信大家都已经有了想法,暴力?高大上的解法?还是先PASS,有的时候(数据量不是特别大的时候),就可以先过一发暴力,如果不行,再换其他方法。我先附上暴力解法:
#include
#include
#include
using namespace std;
int a[1000000];
int main()
{
int i;
int n;
int num;
while(cin>>n)
{
memset(a,0,sizeof(a));
for(i=0;i>num;
a[num]++;
if(a[num]==(n+1)/2)
{
cout<
耗时998ms 快要超时了,对于我这个新手,这个暴力用的方法也是使我大吃一惊,用数组的下标来模拟这些数字,而数组中的值就是这个下标出现的次数。很妙。其实还有不用暴力的解法:
#include
#include
using namespace std;
int a[1000000];
int main()
{
int i,n;
while(scanf("%d",&n)!=EOF)
{
for(i=0;i
先把数组的数据排序,然后 直接 去找那个下标(n+1)/2 ,在数组的位置需要 -1,就直接找出答案。
如果满足的数据在前面,那么(n+1)/2-1就是在满足数据的最后的那一位。如果满足的数据在最后的话:
满足数据在中间的话也是满足的:
看来是排序让他保证了不会错。耗时202ms ,是很好了。
2.美素数
HDU - 4548
题面:
小明对数的研究比较热爱,一谈到数,脑子里就涌现出好多数的问题,今天,小明想考考你对素数的认识。
问题是这样的:一个十进制数,如果是素数,而且它的各位数字和也是素数,则称之为“美素数”,如29,本身是素数,而且2+9 = 11也是素数,所以它是美素数。
给定一个区间,你能计算出这个区间内有多少个美素数吗?
Input
第一行输入一个正整数T,表示总共有T组数据(T <= 10000)。
接下来共T行,每行输入两个整数L,R(1<= L <= R <= 1000000),表示区间的左值和右值。
Output
对于每组数据,先输出Case数,然后输出区间内美素数的个数(包括端点值L,R)。
每组数据占一行,具体输出格式参见样例。
Sample Input
3
1 100
2 2
3 19
Sample Output
Case #1: 14
Case #2: 1
Case #3: 4
这个题也是,起初想到了 暴力遍历,判断,结局不用说,肯定超时,又想到素数打表,但是很奇怪,还是超时。
const int maxn=10000000;
bool vis[maxn];
int Prime[maxn];
int cnt;
void fun()
{
cnt = 0;
memset(vis,true,sizeof(vis));
vis[0] = vis[1] = false;
vis[2] = true;
for(int i = 2 ; i<=maxn ; i++)
{
if(vis[i])
{
Prime[cnt++] = i;
for(int j = i+i ; j<=maxn; j+=i)
{
vis[j] = false;
}
}
}
}
这个题是个双打表,解法很妙:
直接把每个数 是否是素数和 它每个位的和 是否是素数 ,全部打好表,来判断,如果只打了是否它本身是不是素数,然后在输入数据的时候,再现判断它每个位是否是素数 ,就会超时,造成没必要的麻烦。打完表后,这个ans[ ]数组中的数据就是2到这个 下标范围中所有既是素数,又是每位和 也是素数 的数量。在下面的输入数据时 ,就直接 ans[右范围]-ans[左范围-1],这里要减一个 1,数组第一个数据位置为0。
#include
#include
#include
#include
using namespace std;
const int maxn=1000005;
typedef long long ll;
int ans[maxn];
bool vis[maxn];
int Prime[maxn];
int cnt;
void fun()
{
cnt = 0;
memset(vis,true,sizeof(vis));
vis[0] = vis[1] = false;
vis[2] = true;
for(int i = 2 ; i<=maxn; i++)
{
if(vis[i])
{
Prime[cnt++] = i;
for(int j = i+i ; j<=maxn; j+=i)
{
vis[j] = false;
}
}
}
}
int fun(int i)
{
int sum=0;
while(i)
{
sum=sum+i%10;
i=i/10;
}
return sum;
}
int main()
{
int sum=0;
fun();
for(int i=2;i<=maxn;i++)
{
if(vis[i]&&vis[fun(i)])
sum++;
ans[i]=sum;
}
int t;
cin>>t;
int kase=0;
while(t--)
{
int left,right;
cin>>left>>right;
int x=ans[right]-ans[left-1];
printf("Case #%d: %d\n",++kase,x);
}
return 0;
}
耗时 62 ms.完美。
3.Jamie and Alarm Snooze 来自 codeforces 916A
题面:
约翰喜欢睡觉。有一天,他必须以hh:mm起床。然而,他讨厌醒来,所以他想通过在NICE时间设置闹钟来唤醒不那痛痛。然后他会每隔x分钟按下贪睡按钮,直到hh:mm到达,然后才会醒来。他想知道按下贪睡按钮所需的最小次数是多少。
如果它包含数字'7',则被认为是NICE。例如,13:07和17:27是NICE,而00:48和21:34不是NICE。
请注意,警报和唤醒时间设置的时间不是同一天。 John可以设定一个NICE时间,这样他就可以醒来...... hh:mm。
形式上,找到尽可能小的非负整数y,使得hh:mm之前的时间x·y分钟的时间表示包含数字'7'。
约翰使用二十四小时制,所以在23:59到00:00之后。
输入
每个输入包含2行。
第一行是整数x(0
产量
输出他按下按钮的最小次数。
Example
3 11 23
2
5 01 07
0
代码实现:
#include
#include
#include
using namespace std;
int main(){
int x,h,m;
while(cin>>x){
int ans=0;
cin>>h>>m;
if(m%10==7||h%10==7) cout<<"0"<
这个题就是用暴力的解法,有个坑点,就是 时间 范围 是00:00 到 23:59 如果时间减到 00:00以后 ,就会 再来一天 ,从 24:00再开始减时间,这个 需要考虑,还有 这句话:形式上,找到尽可能小的非负整数y,使得hh:mm之前的时间x·y分钟的时间表示包含数字'7',时减过时间厚的时间点 要有数字 7,不是 在 x*y 时间 减去过程中出现 数字7.
上面代码 简洁清晰,希望大家可以学学。如果 题目 是暴力求解的 话,可以把代码实现变得简单点,将代码变得简单清晰也是一种技巧吧,不用多余的步骤,以免耗时超时。
看看我一开始过得代码:
#include
#include
using namespace std;
int main()
{
int n;
int h,m;
int h1,m1;
int k=0;
int shuju;
int flag=0,lock=0;
int xianzaishijian;
while(scanf("%d%d%d",&n,&h,&m)!=EOF)
{
flag=0,lock=0;
int zongshijian=h*60+m;
for(k=0;;k++)
{
flag=0,lock=0;
xianzaishijian=zongshijian-k*n;
if(xianzaishijian<0)
xianzaishijian+=24*60;
h1=xianzaishijian/60;
m1=xianzaishijian%60;
while(h1)
{
shuju=h1%10;
h1=h1/10;
if(shuju==7)
{
printf("%d\n",k);
flag=1;
break;
}
}
if(!flag)
{
while(m1)
{
shuju=m1%10;
m1=m1/10;
if(shuju==7)
{
printf("%d\n",k);
lock=1;
break;
}
}
}
if(flag||lock)
break;
}
}
return 0;
}
不忍直视,代码 又乱 又冗长,又不好理解。