7.14.實驗 解題參考

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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章