积分赛三订正
H - 不要62 HDU - 2089
原题
杭州人称那些傻乎乎粘嗒嗒的人为62(音:laoer)。
杭州交通管理局经常会扩充一些的士车牌照,新近出来一个好消息,以后上牌照,不再含有不吉利的数字了,这样一来,就可以消除个别的士司机和乘客的心理障碍,更安全地服务大众。
不吉利的数字为所有含有4或62的号码。例如:
62315 73418 88914
都属于不吉利号码。但是,61152虽然含有6和2,但不是62连号,所以不属于不吉利数字之列。
你的任务是,对于每次给出的一个牌照区间号,推断出交管局今次又要实际上给多少辆新的士车上牌照了。
Input
输入的都是整数对n、m(0<n≤m<1000000),如果遇到都是0的整数对,则输入结束。
Output
对于每个整数对,输出一个不含有不吉利数字的统计个数,该数值占一行位置。
Sample Input
1 100
0 0
Sample Output
80
我的答案
这题我是用纯暴力写的(好像这题是dp练习题),用cin和cout就是超时TLE(限时1000ms),然后我换了个输入方法scanf就勉强过了(951ms)。
#include <iostream>
#include<cstdio>
using namespace std;
int main()
{
int m,n,i,p,cnt;
while(1)
{
scanf("%d%d",&n,&m);//cin>>n>>m;
cnt=m-n+1;
if(n==0&&m==0) break;
for(i=n;i<=m;i++)
{
for(p=i;p>0;)
{
if(p%10==4) {cnt--;break;}
if(p%100==62)/*p<i) if(j==2&&q==6)*/ {cnt--;break;}
p=p/10;
}
}
printf("%d\n",cnt);//cout<<cnt<<endl;
}
return 0;
}
A - 抱歉 HDU - 1418
原题
非常抱歉,本来兴冲冲地搞一场练习赛,由于我准备不足,出现很多数据的错误,现在这里换一个简单的题目:
前几天在网上查找ACM资料的时候,看到一个中学的奥数题目,就是不相交的曲线段分割平面的问题,我已经发到论坛,并且lxj 已经得到一个结论,这里就不
多讲了,下面有一个类似的并且更简单的问题:
如果平面上有n个点,并且每个点至少有2条曲线段和它相连,就是说,每条曲线都是封闭的,同时,我们规定:
1)所有的曲线段都不相交;
2)但是任意两点之间可以有多条曲线段。
如果我们知道这些线段把平面分割成了m份,你能知道一共有多少条曲线段吗?
Input
输入数据包含n和m,n=0,m=0表示输入的结束,不做处理。
所有输入数据都在32位整数范围内。
Output
输出对应的线段数目。
Sample Input
3 2
0 0
Sample Output
3
我的答案
这里的数据就是要用long long不然就WA了。显而易见,这题就是多边形(近似)的边数与分割的问题,n个点把平面分成两份就是可以形成一个n边形,三份就是n+1……以此类推m份就是n+m-2。
#include <iostream>
using namespace std;
int main()
{
long long int m,n;
while(cin>>n>>m)
{
if(n==0&&m==0) break;
cout<<n+m-2<<endl;
}
return 0;
}
I - 不可摸数 HDU - 1999
原题
s(n)是正整数n的真因子之和,即小于n且整除n的因子和.例如s(12)=1+2+3+4+6=16.如果任何
数m,s(m)都不等于n,则称n为不可摸数.
Input
包含多组数据,首先输入T,表示有T组数据.每组数据1行给出n(2<=n<=1000)是整数。
Output
如果n是不可摸数,输出yes,否则输出no
Sample Input
3
2
5
8
Sample Output
yes
yes
no
答案
我感觉我总是TLE,复制一下以后看看。
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <cstring>
#include <queue>
#include <string>
using namespace std;
const int maxn = 1000000+10;
const int maxm = 1000+10;
int sum[maxn],sign[maxm];
int main()
{
memset(sum,0,sizeof(sum));
memset(sign,0,sizeof(sign));
for(int i = 1; i <= 500000; i++)//筛法求s(n),并用数组sum存起来
{
for(int j = 2*i; j <= 1000000; j += i)
{
sum[j] += i;
}
}
for(int i = 1; i <= 1000000; i++)//标记1000以内的s(m)
if(sum[i] < 1000)
sign[sum[i]] = 1;
int t,n;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
if(!sign[n])
puts("yes");
else
puts("no");
}
return 0;
}