pat a 1103 integer factorization

来源:互联网 发布:通达信软件官网 编辑:程序博客网 时间:2024/06/02 06:56

生词:
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; }