初學ACM - 半數集(Half Set)問題 NOJ 1010 / FOJ 1207

 題目重述:ios

問題描述數組

要求找出具備下列性質數的個數(包含輸入的天然數n):
先輸入一個天然數n(n<=1000),而後對此天然數按照以下方法進行處理:
1. 不做任何處理;
2. 在它的左邊加上一個天然數,但該天然數不能超過原數的一半;
3. 加上數後,繼續按此規則進行處理,直到不能再加天然數爲止.
函數

輸入測試

一個天然數nspa

輸出code

一個數,表示知足條件的數的個數orm

樣例輸入遞歸

6ci

樣例輸出string

6

提示

樣例說明:知足條件的數是6,16,26,126,36,136


    假設不考慮重複的狀況,那麼採用下面公式便可:

                                                

    只須要一個數組,很容易寫出下面這個程序:

#include <iostream>
#include <cstring>
using namespace std;


int ans[100005];

int main()
{
    int n;
    cin>>n;
    for(int i=0; i<=n; i++) 
        ans[i] = 1;

    for(int i=2; i<=n; i++)
    {
        for(int j=1; j<=i/2; j++)
            ans[i] += ans[j];
    }

    cout<<ans[n]<<endl;

    return 0;
}

    

    這個程序已經能夠AC南京郵電大學OJ的測試數據了,但卻過不去FOJ 1207,緣由是沒有考慮重複生成的狀況。

    下面咱們來看一個重複生成的狀況:

        60-(添加24)>2460-(添加1)>12460和60-(添加4)>460-(添加2)>2460-(添加1)>12460    

    也就是說,set(j/10)中的部分元素已經在 set(j%10)中生成了,而判斷條件就是 j>10&&(j/10<=((j%10)/2))

    按照這個思路,改進一下程序:

#include <iostream>
#include <cstring>
using namespace std;


int ans[100005];

int main()
{
    int n;
    while(cin>>n)
    {
        for(int i=0; i<=n; i++) 
            ans[i] = 1;

        for(int i=2; i<=n; i++)
        {
            for(int j=1; j<=i/2; j++)
            {
                ans[i] += ans[j];
                if (j>10&&(j/10<=((j%10)/2)))
                {
                    ans[i] -= ans[j/10];
                }
            }
        }

        cout<<ans[n]<<endl;
    }
    return 0;
}

    穩穩的AC~

    

    附上遞歸函數:

int numofSet(int n)
{
    int ans=1;
    if(a[n]>1 || n==1)
        return a[n];
    for(int i=1;i<=n/2;i++)
    {
        ans+=numofSet(i);
        if(i>10&&(i/10<=((i%10)/2)))     //剔除重複元素的判斷語句
            ans-=a[i/10];
    }
    a[n]=ans;
    return ans;
}
相關文章
相關標籤/搜索