c++花朵数

来源:互联网 发布:javascript视教程下载 编辑:程序博客网 时间:2024/05/01 17:01




这题目我一开始考虑的很烦,不知道如何保存这21位数,用数组,那有怎么计算阶乘呢,那我们考虑如果能把21个数分成三个部分,这样一个部分的数超过就进位

所以我写了一个计算阶乘的函数

void fang(int x)  
{  
    long int a = 0,b = 0,c = 1;  
    for(int i = N;i > 0; --i)  
    {  
        c = c * x;  //1-7位的数 
        a = a * x;  //8-15位的数 
        b = b * x;  //16-21位的数 
        while(b > 9999999)  //第15的数>10;则需进位到第16位 
        {  
            b -= 10000000;  
            a += 1;  
        }         
        while(c > 9999999)   //第7的数>10;则需进位到第8位 
        {  
            c -= 10000000;  
            b += 1;  
            while(b > 9999999) //再次判断第15位是否超过10 
            {  
                b -= 10000000;  
                a += 1;  
            }  
        }  
    }  
  
    int d;  
    int e = N - 14;  
    while(a)  //将16-21位的数依次存到数组arr[x][15]-arr[x][20] 
    {  
        d = a % 10;  
        arr[x][N - (e--)] = d;  
        a = a / 10;  
    }  
  
    e = N - 7;  
    while(b)   //将8-15位的数依次存到数组arr[x][7]-arr[x][14] 
    {  
        d = b % 10;  
        arr[x][N - (e--)] = d;  
        b = b / 10;  
    }  
  
    e = N;   //将1-7位的数依次存到数组arr[x][0]-arr[x][6] 
    while(c)  
    {  
        d = c % 10;  
        arr[x][N - (e--)] = d;  
        c = c / 10;  
    }  

最关键的解决了,那我怎么来比较与原来数字是否相等,这是再次出现的问题,所以我一开始天真的想把所有阶乘加起来再比较形成的数,那太烦了,也感觉太low,直接考虑把阶乘求出来的和计算位数,看是否有21位,那这就是我们要的数。

if(0 == add[N - 1]) continue; //add是阶乘求和后保存的数组


那么有了阶乘和的函数,那有哪些数需要求阶乘和呢,我打算用循环来计算21位数中0-9出现的次数

for(cot[9] = 0;cot[9] <= 9; ++cot[9])  
    {  
        for(cot[8] = 0;cot[8] <= N - cot[9]; ++cot[8])  
        {  
            for(cot[7] = 0;cot[7] <= N - cot[9] - cot[8]; ++cot[7])  
            {  
                for(cot[6] = 0;cot[6] <= N - cot[9] - cot[8] - cot[7]; ++cot[6])  
                {  
                    for(cot[5] = 0;cot[5] <= N - cot[9] - cot[8] - cot[7] - cot[6]; ++cot[5])  
                    {  
                        for(cot[4] = 0;cot[4] <= N - cot[9] - cot[8] - cot[7] - cot[6] - cot[5]; ++cot[4])  
                        {  
                            for(cot[3] = 0;cot[3] <= N - cot[9] - cot[8] - cot[7] - cot[6] - cot[5] - cot[4]; ++cot[3])  
                            {  
                                for(cot[2] = 0;cot[2] <= N - cot[9] - cot[8] - cot[7] - cot[6] - cot[5] - cot[4] - cot[3]; ++cot[2])  
                                {  
                                    for(cot[1] = 0;cot[1] <= N - cot[9] - cot[8] - cot[7] - cot[6] - cot[5] - cot[4] - cot[3] - cot[2]; ++cot[1])  
                                    {  
                                        cot[0] = N - cot[9] - cot[8] - cot[7] - cot[6] - cot[5] - cot[4] - cot[3] - cot[2] - cot[1];  

这看起来很多,其实就是9个循环,暴力求0-9出现的次数

我们通过函数把0-9的21次方都保存到了arr[10][21]数组中了

接下来就是求add和了

int cota[10],add[N];  
  
                                        for(int j = 0;j < N; ++j)  
                                        {  
                                            add[j] = 0;  
                                        }  
                                        for(int k = 0;k < 10; ++k)  
                                        {  
                                            cota[k] = 0;  
                                        }  
  
                                        //求该数的每个位上的数字的N次方的和  
                                        for(int l = 0;l < 10; ++l)  //l这个循环代表0-9数字 
                                        {  
                                            for(int m = 1;m <= cot[l]; ++m)  //代表的l的数字出现的个数 
                                            {  
                                                for(int n = 0;n < N; ++n)  
                                                {  
                                                    add[n] += arr[l][n];  //将计算的l的21次方保存到add数组 
                                                    while(add[n] > 9)  //进位操作 
                                                    {  
                                                        add[n] -= 10;  
                                                        add[n + 1]++;  
                                                    }  
                                                }  
  
                                            }  
                                        }  

得到了总和的数之后,为了保险,我们统计一下数字,与刚一开始cot[10]数组中生成的数比较是否一致

   //计数和中每个数字出现的次数  
                                        for(int o = 0;o < N; ++o)  
                                        {  
                                            cota[add[o]]++;  
                                        }  
  
                                        //将和中每个数字出现的次数与该数中每个数字出现的次数进行比较  
                                        int flag = 1;  
                                        for(int p = 0;p < 10; ++p)  
                                        {  
                                            if(cot[p] != cota[p])  
                                            {  
                                                flag = 0;  
                                                break;  
                                            }  
                                        }  
                                        //当该数不符合要求时执行下一次循环,不输出该数  
                                        if(0 == flag) continue;  

如果一致输出这21位数,解决


下面附上源码

#include<iostream>  
#define N 21  
  
using namespace std;  
  
void fang(int x);  
int arr[10][21];  
  
int main()  
{  
    int cot[10];  
  
    for(int i = 0;i < 10; ++i)  
    {  
        cot[i] = 0;  
        fang(i);  
    }  
  
    //生成一个N位数并计数该数中每个数字出现的次数  
    for(cot[9] = 0;cot[9] <= 9; ++cot[9])  
    {  
        for(cot[8] = 0;cot[8] <= N - cot[9]; ++cot[8])  
        {  
            for(cot[7] = 0;cot[7] <= N - cot[9] - cot[8]; ++cot[7])  
            {  
                for(cot[6] = 0;cot[6] <= N - cot[9] - cot[8] - cot[7]; ++cot[6])  
                {  
                    for(cot[5] = 0;cot[5] <= N - cot[9] - cot[8] - cot[7] - cot[6]; ++cot[5])  
                    {  
                        for(cot[4] = 0;cot[4] <= N - cot[9] - cot[8] - cot[7] - cot[6] - cot[5]; ++cot[4])  
                        {  
                            for(cot[3] = 0;cot[3] <= N - cot[9] - cot[8] - cot[7] - cot[6] - cot[5] - cot[4]; ++cot[3])  
                            {  
                                for(cot[2] = 0;cot[2] <= N - cot[9] - cot[8] - cot[7] - cot[6] - cot[5] - cot[4] - cot[3]; ++cot[2])  
                                {  
                                    for(cot[1] = 0;cot[1] <= N - cot[9] - cot[8] - cot[7] - cot[6] - cot[5] - cot[4] - cot[3] - cot[2]; ++cot[1])  
                                    {  
                                        cot[0] = N - cot[9] - cot[8] - cot[7] - cot[6] - cot[5] - cot[4] - cot[3] - cot[2] - cot[1];  
                                        int cota[10],add[N];  
  
                                        for(int j = 0;j < N; ++j)  
                                        {  
                                            add[j] = 0;  
                                        }  
                                        for(int k = 0;k < 10; ++k)  
                                        {  
                                            cota[k] = 0;  
                                        }  
  
                                        //求该数的每个位上的数字的N次方的和  
                                        for(int l = 0;l < 10; ++l)  //l这个循环代表0-9数字 
                                        {  
                                            for(int m = 1;m <= cot[l]; ++m)  //代表的l的数字出现的个数 
                                            {  
                                                for(int n = 0;n < N; ++n)  
                                                {  
                                                    add[n] += arr[l][n];  //将计算的l的21次方保存到add数组 
                                                    while(add[n] > 9)  //进位操作 
                                                    {  
                                                        add[n] -= 10;  
                                                        add[n + 1]++;  
                                                    }  
                                                }  
  
                                            }  
                                        }  
                                        //判断得到的和是不是一个21位数  
                                        if(0 == add[N - 1]) continue;  
  
                                        //计数和中每个数字出现的次数  
                                        for(int o = 0;o < N; ++o)  
                                        {  
                                            cota[add[o]]++;  
                                        }  
  
                                        //将和中每个数字出现的次数与该数中每个数字出现的次数进行比较  
                                        int flag = 1;  
                                        for(int p = 0;p < 10; ++p)  
                                        {  
                                            if(cot[p] != cota[p])  
                                            {  
                                                flag = 0;  
                                                break;  
                                            }  
                                        }  
                                        //当该数不符合要求时执行下一次循环,不输出该数  
                                        if(0 == flag) continue;  
                                        for(int q = N - 1;q >= 0; --q)  
                                            cout<<add[q];  
                                        cout<<endl;  
                                    }  
                                }  
                            }  
                        }  
                    }  
                }  
            }  
        }  
    }  
    return 0;  
}  
  
//该函数用来求x的21次方,并将所求结果存储在数组arr[x]中  
void fang(int x)  
{  
    long int a = 0,b = 0,c = 1;  
    for(int i = N;i > 0; --i)  
    {  
        c = c * x;  //1-7位的数 
        a = a * x;  //8-15位的数 
        b = b * x;  //16-21位的数 
        while(b > 9999999)  //第15的数>10;则需进位到第16位 
        {  
            b -= 10000000;  
            a += 1;  
        }         
        while(c > 9999999)   //第7的数>10;则需进位到第8位 
        {  
            c -= 10000000;  
            b += 1;  
            while(b > 9999999) //再次判断第15位是否超过10 
            {  
                b -= 10000000;  
                a += 1;  
            }  
        }  
    }  
  
    int d;  
    int e = N - 14;  
    while(a)  //将16-21位的数依次存到数组arr[x][15]-arr[x][20] 
    {  
        d = a % 10;  
        arr[x][N - (e--)] = d;  
        a = a / 10;  
    }  
  
    e = N - 7;  
    while(b)   //将8-15位的数依次存到数组arr[x][7]-arr[x][14] 
    {  
        d = b % 10;  
        arr[x][N - (e--)] = d;  
        b = b / 10;  
    }  
  
    e = N;   //将1-7位的数依次存到数组arr[x][0]-arr[x][6] 
    while(c)  
    {  
        d = c % 10;  
        arr[x][N - (e--)] = d;  
        c = c / 10;  
    }  

原创粉丝点击