pat a 1103 integer factorization

生詞:
factorization 因數分解;P-th power p次冪;tie 平局,兩種方案相同;
sequence { a1, a2, … aK } is said to be larger than { b1, b2, … bK } if there exists 1<=L<=K such that ai=bi for ibL
這句是按字典序排序的意思, { a1, a2, … aK }比 { b1, b2, … bK }大就是指{ a1, a2, … aK }的字典序比 { b1, b2, … bK }大。

題目差點沒讀懂。讀到輸出格式倒是大致明白了。第一反應不會,但是先試試。
慘不忍睹,編譯不過的第一版:

#include<cstdio>
#include<vector>
#include<cmath>
#include<algorithm> 
using namespace std;
vector<int> s,smax;
int basummax=0;
int N,K,P;
/*標答的思路是預先生成需要的平方數數列,因此只需要從大到小遞歸即可實現遞減排序*/
bool cmp(int a,int b){
    return a>b;
} 
//不要在找到一組解後才判斷字典序關係,應該讓index從大到小選擇
vector<int> zidianxu(vector<int> s,vector<int> smax){
    vector<int> res; 
    /*正確寫法:
    vector<int>::iterator it=s.begin();
    sort(it,it+s.size(),cmp);*/
    sort(s,s+s.size(),cmp);//錯誤!
    sort(smax,smax+smax.size(),cmp);//錯誤!
    for(int i=0;i<s.size();i++){
        if(s[i]==smax[i]){
            continue;
        }else{
            s[i]>smax[i]?res=s:res=smax;
            break;
        }

    }
    return res; 

}
void DFS(int index, int sum){
    if(index>K)return;
    if(sum>N)return;
    if(sum==N&&index==K){
            int basum=0;//底數和
/*假如有5個方案,計算底數和的時間複雜度是O(K)(取時間複雜度最大的步驟的複雜度),容易超時。如果把底數和作爲一個參數,則複雜度爲O(1)*/           
            for(vector<int>::iterator it=s.begin();it!=s.end();it++){
              basum+=*it;
                } 
        if(basum>basummax){
            smax=s;//vector間可以直接賦值 
        }else if(bsum==basummax){
            smax=zidianxu(s,smax);
        } else{
            return;
        }
    }
    /*我的想法是N=400,P最小=2的情況時,底數選取的範圍最大:1~20,可覆蓋所有情況,但這樣時間複雜度極高。標答的思路是當輸入N,P時,將所有小於N的平方數計算並存儲結果,然後從中選K個。另一個錯誤是s[index]中的數可以相同,我沒有枚舉這種情況*/
    for(int i=1;i<20;i++){
        s[index]=i;//vector不可以這樣賦值,只能用push_back()!
        /*假如有5個方案,計算底數和的時間複雜度是O(K)(取時間複雜度最大的步驟的複雜度),如果把底數和作爲一個參數,則複雜度爲O(1)*/
        DFS(index+1,sum+pow(i,P));
    /*分析遞歸的時候分析1:遞歸有幾個參數;2.遞歸的時候有幾個分支,分支參數的變化。*/    
        continue;
    }

}
int main(){
    scanf("%d %d %d",&N,&K,&P);
    DFS(0,0);
    if(smax.empty()){
        printf("Impossible");
    } else{
        printf("%d =",N);
        for(int i=0;i<K;i++){
            printf(" %d^%d",smax[i],P);
            if(i<k-1){
                printf(" +");
            }
        }
    }
    return 0;
}

把自己的想法儘快用代碼表達出來,反正通過的可能幾乎沒有。之所以自己先寫一遍,是爲了儘可能多的找到自己的薄弱點,雖然從頭到腳都是弱點。至少if-else,for(){輸出}我還是能寫好的。
下面是標答:

#include<cstdio>
#include<vector>
#include<algorithm>
#include<cmath>
using namespace std;
int n,k,p,maxFacSum=-1;//最大底數和 
vector<int> fac,ans,temp;//預處理的平方數,最優底數序列,當前底數序列 
/*int power(int x){
    int ans=1;
    for(int i=0;i<p;i++){
        ans*=x;
    }
    return ans;
}*/ 
//預處理fac數組 
void init(){
    int i=0,temp=0;
    while(temp<=n){
        fac.push_back(temp);
        temp=pow(++i,p);
    } 
}
void DFS(int index,int nowK,int sum,int facSum){
    if(sum==n&&nowK==k){
        if(facSum>maxFacSum){
            ans=temp;
            maxFacSum=facSum;
        }
        return;
    }
    if(sum>n||nowK>k)return;
    if(index-1>=0){
        temp.push_back(index);
        DFS(index,nowK+1,sum+fac[index],facSum+index);
        temp.pop_back();
        DFS(index-1,nowK,sum,facSum); 
    }
} 
int main(){
    scanf("%d%d%d",&n,&k,&p);
    init();
    DFS(fac.size()-1,0,0,0);
    if(maxFacSum==-1)printf("Impossible\n");
    else{
        printf("%d = %d^%d",n,ans[0],p);
        for(int i=1;i<ans.size();i++){
            printf(" + %d^%d",ans[i],p);
        }
    }
    return 0;
}

標答的思路就是先生成備選平方數,然後再用DFS輪。
我的思路是想到那寫到那,全部用最笨最暴力的枚舉解決。
傻。
默寫失敗第一版,“運行超時”

#include<cstdio>
#include<vector>
using namespace std;//常忘1 
vector<int> powSes,tempRes,maxRes;//vector<int>常忘2 
int n,k,p,maxKSum=-1;
int power(int x){
    int ans=1;
    for(int i=0;i<p;i++){
        ans=ans*x;
    }
    return ans;
}
void init(){
    int temp=0;
    for(int i=0;;i++){//爲了保證第i位的數據是i^p,所以第0位的數據是0 
        temp=power(i);
        if(temp>n)return;
        powSes.push_back(temp);
    }
}
void DFS(int index,int sum,int kSum,int kc){
    if(sum==n&&kc==k){
        if(kSum>maxKSum){
            maxRes=tempRes;
            maxKSum=kSum;
        }/*else if(kSum==maxKSum){
            for(int i=0;i<k;i++){
                if(maxRes[i]<tempRes[i]){
                    maxRes=tempRes;
                    break;
                }else if(maxRes[i]>tempRes[i]){
                    break;
                }
            }將次方數組從大到小選數,後面的滿足條件的序列其字典序必然小於前面先滿足條件的序列 
        }*/
        return; 
    }
    if(sum>n||kc>k)return;
    /*while(index-1>=0){//假設index是5,兩條DFS子函數都執行完了,因爲while(5-1>=0),故又重複執行一遍,死循環。 
        tempRes.push_back(powSes[index]);
        要保存的是底數序列,不是次方序列! 
        DFS(index,sum+powSes[index],kSum+index,kc+1);
        tempRes.pop_back();
        DFS(index-1,sum,kSum,kc);
    }*/
    if(index-1>=0){
        tempRes.push_back(index);
        DFS(index,sum+powSes[index],kSum+index,kc+1);
        tempRes.pop_back();
        DFS(index-1,sum,kSum,kc);

    }
}
int main(){
    scanf("%d %d %d",&n,&k,&p);
    init();
    DFS(powSes.size()-1,0,0,0);
    if(maxKSum==-1)printf("Impossible");
    else{
        printf("%d =",n);
        for(int i=0;i<k;i++){
            printf(" %d^%d",maxRes[i],p);
            if(i<k-1){
                printf(" +");
            }
            }       
        }
    return 0; 
}
發佈了25 篇原創文章 · 獲贊 4 · 訪問量 8326
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章