这道题拿到手,感觉十分简单。
真的写起来的时候,感觉根本写不来。
可能是刚吃完饭,没什么脑子。
于是只能网上学习代码。
下面的代码转自:http://blog.csdn.net/kakitgogogo/article/details/52086309
这里我来给他的代码写上详细的注释:

#include <iostream>  
#include <cstring>  
#include <cstdio>  
#include <cstdlib>  
#include <vector>  
#include <cmath>  
#include <algorithm>  
using namespace std;  

int n,k,p;  
vector<int>res;  //储存结果 
vector<int>mypow; 
/*
这一手vector非常nice
我在写这题目的时候,是不断的执行pow()函数
但实际上,多次执行的pow函数会使得程序变慢很多
不如用一个数组存储,只需要不到一百次的运算
就可以计算出所有pow()函数的结果储存在mypow数组中
需要的时候,直接在这个数组里通过下标找就可以了
*/ 
int max_idx;  //计算出最大的ni值,也就是以p为指数的最大底数 

void init_pow()  //找max_idx以及填满mypow数组 
{  
    for(int i=0;;i++)  // 从0开始,最大的好处,就是i与mypow【i】一一对应,如果从1开始的话,自己思维就要自己加一了 
    {  
        int num=1;  
        for(int j=0;j<p;j++)  
        {  
            num*=i;  //计算i^p是否超过最大值 
        }  
        mypow.push_back(num);  //mypow里面存放的是i从1到max_idx的p次方的结果,便于直接调用 
        max_idx=i;  
        if(num>=n) return;  //其实这里400改成n更好,可以少算几步,不过也只是几步而已,无伤大雅 
    }  
}  


int Max=0;  //找到和最大的那组res 
void dfs(int target,int count,int high,vector<int>fac)  
{  
    if(count==0)  //count = 0的时候,说明所有底数都已就位 
    {  
        if(target==0)  //如果此时他们的和达到了题目所给的值 
        {  
            if(res.empty()) res=fac; //res还不存在的话就赋值给res 
            else  //存在的话就要比较和谁大 
            {  
                int sum=0;  
                for(int i=0;i<k;i++)  
                {  
                    sum+=fac[i];  
                }  
                if(sum>Max)   //如果和要是大一点的话,就改变res 
                {  
                    Max=sum;  //可是题目中明明说要按字典序呀,这里貌似并没有操作 
                    res=fac;  //原因是dfs的时候就是按字典序dfs的,所以就很方便的不用判断啦 
                }  
            }  
        }  
        return;  
    }  
    if(target<count) return;  //如果剩下的target,连每个底数是1都支撑不了的话,说明一定不存在这样的组合
                              //实际上我测试了一下这里的剪枝是没有用的。。。 
    while(mypow[high]>target-count+1) high--;    //找到最大的并且刚好适合的mypow,从大到小递归 
    for(int i=high;mypow[i]>=target/count ;i--)  //这里为什么不写成i > 0呢,明明可以一直dfs下去的啊                                              
    {                                            //亲测这里写成i>0会超时,先解释一下为什么写成 mypow[i]>=target/count,target/count的意思是,剩下的i^p平均要负担的数量 
        if(target>=mypow[i])                     //因为如果小于的话,就说明,在这种mypow下,剩下的数字的底数就会比当前位要大,因为当前位比平均要小,剩下的至少某一个数必然比平均大 
        {                                        //但是事实上,题目要求从大到小有规律的输出,所以这里也是非常妙的 
            fac[count-1]=i;                      //不仅可以减少很多的dfs时间,而且使得res数组里,是从大到小有序的 
            dfs(target-mypow[i],count-1,i,fac);  
        }  
    }  
}  

int main()  
{  
    cin>>n>>k>>p;  
    init_pow();  
    vector<int>fac(k);  
    dfs(n,k,max_idx,fac);  
    if(!res.empty())  
    {  
        reverse(res.begin(),res.end());  //转一下 
        printf("%d = %d^%d",n,res[0],p);  
        for(int i=1;i<res.size();i++)  
        {  
            printf(" + %d^%d",res[i],p);  
        }  
    }  
    else   
    {  
        printf("Impossible");  
    }  
}

数论的题目果然难
继续加油!
总有一天小菜鸡也会变成大佬的

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐