ProblemA(HDU1215)
ProblemB(HDU1286)
这两题是上课例题,不再赘述了。
ProblemC(HDU1406)
【一】这题的数据可以直接判断,在num1和num2之间的数是否符合要求。但有个巨坑需要注意,num1和num2不一定是大小顺序给出的!!
【二】但既然学会了筛选法,很明显可以看到这题先预处理,将10000以内的数据先用判断函数跑一遍,存表再做会有更高的效率。
而且,作为一个解题经验技巧来说,这个完数的条件比较苛刻,也就是所很多很多数里面才能出现很少的数符合条件,而10000也不是特别大。那么抱着好奇的心态我会让跑出来的结果先输出一遍,看看到底有多少个数。
结果当然没有让我失望,只有6,28,496,8128这四个完数!大家都意识到了吧,预处理都可以精简到几乎没有了!不用占用运行的时间咯~
//裸版
#include <stdio.h>
int sum(int n)
{
int s = 0, i;
for (i = 1; i <= n/2; i++)
{
if(n%i == 0)
s += i;
}
return s;
}
int main()
{
int n, num1, num2, i, count;
scanf("%d", &n);
while(n--)
{
scanf("%d%d", &num1, &num2);
count = 0;
if(num1 > num2)
{
int t=num1;
num1=num2;
num2=t;
}
for (i = num1; i <= num2; i++)
{
if(i == sum(i))
count++;
}
printf("%d\n", count);
}
return 0;
}
//精装版
#include <stdio.h>
int main()
{
int n,a,b,i,count;
int pn[4]={6,28,496,8128};
scanf("%d",&n);
while(n--)
{
count=0;
scanf("%d %d",&a,&b);
if(a>b) a^=b^=a^=b;//炫个技,我见过的交换两个数的最短代码...
for(i=0;i<4;i++)
if(a<=pn[i]&&pn[i]<=b)
count++;
printf("%d\n",count);
}
return 0;
}
ProblemD(HDU4548)
典型的筛法求素数,打表预处理。
先用筛法筛出数据范围内的素数,再将每个数以内有多少个素数递推求出来存在表primeNums里。之后求a和b直接就可以直接用primeNums[b]-primeNums[a]。
这个算法非常有效率。求primeNums表其实是对需求的一个预处理,而这个预处理前面需要用到的素数表其实又是一个叠加的预处理。
#include <stdio.h>
#include <string.h>
const int MAX_N = 1000001;
bool isPrime(int n)
{
if (n == 2) return true;
for (int r = 2; r * r <= n; r++)
{
if (n % r == 0) return false;
}
return true;
}
bool isMeiPrime(int n)
{
int d = 0;
while (n)
{
d += n % 10;
n /= 10;
}
return isPrime(d);
}
int primeNums[MAX_N];
bool primes[MAX_N];
void seive()
{
memset(primes, 0, MAX_N * sizeof(bool));
for (int i = 2; i < MAX_N; i++)
{
if (!primes[i])
{
for (int j = i << 1; j < MAX_N; j += i)
{
primes[j] = true;
}
}
}
primeNums[0] = 0, primeNums[1] = 0;
for (int i = 2; i < MAX_N; i++)
{
if (!primes[i] && isMeiPrime(i)) primeNums[i] = primeNums[i-1] + 1;
else primeNums[i] = primeNums[i-1];
}
}
int main()
{
seive();
int T, a, b;
scanf("%d", &T);
for (int t = 1; t <= T; t++)
{
scanf("%d %d", &a, &b);
printf("Case #%d: %d\n", t, primeNums[b] - primeNums[a-1]);
}
return 0;
}
ProblemE(HDU1164)
将一个数分解为几个素数相乘的形式。看数据量很容易想到先预处理,用筛法得到素数表。之后慢慢分解输入的数,遇到能整除的素数就输入,并让其不断缩小即可。
#include <iostream>
#include <cmath>
#include <stdio.h>
#include <string.h>
using namespace std;
bool brr[65536];
int arr[7001];
void FindPrime(void)
{
int i,j,k;
memset(brr,1,sizeof(brr));
k=0;
for(i=2;i<65536;++i)
if(brr[i])
{
for(j=i+i;j<65536;j+=i)
brr[j]=0;
arr[k]=i;
++k;
}
}
int main()
{
int x,i;
FindPrime();
while(scanf("%d",&x)!=EOF)
{
for(i=0;i<=x && !brr[x];++i)
if(x%arr[i]==0)
{
printf("%d*",arr[i]);
x/=arr[i];
--i;
}
printf("%d\n",x);
}
return 0;
}