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;
}