zoukankan      html  css  js  c++  java
  • LightOJ

    先上题目

    Sum of Factorials
                      Time Limit:500MS     Memory Limit:32768KB     64bit IO Format:%lld & %llu

    Description

    Given an integer n, you have to find whether it can be expressed as summation of factorials. For given n, you have to report a solution such that

    n = x1! + x2! + ... + xn! (xi < xj for all i < j)

    Input

    Input starts with an integer T (≤ 10000), denoting the number of test cases.

    Each case starts with a line containing an integer n (1 ≤ n ≤ 1018).

    Output

    For each case, print the case number and the solution in summation of factorial form. If there is no solution then print 'impossible'. There can be multiple solutions, any valid one will do. See the samples for exact formatting.

    Sample Input

    4

    7

    7

    9

    11

    Sample Output

    Case 1: 1!+3!

    Case 2: 0!+3!

    Case 3: 1!+2!+3!

    Case 4: impossible

    Hint

    Be careful about the output format; you may get wrong answer for wrong output format.

      这一题题意就是给你一个数,问哪些数的阶乘等于这个数,并按照样例从小到大输出这些数的每一项,其中每一项只可以用一次,如果不存在这些数,就输出impossible。

          一开始看的时候第一个想到的是用dfs,然后就很轻松地写出的代码,可是发现样例的第四个case卡住了很久,然后就加了一个约束条件,不过时间复杂度还是比较大,跑10个case还是要10ms,而题目要求仅有500ms,于是想了很久怎样优化,看榜发现很多人都很快过了这题,心里有点急,可是心越急就越想不出来,后来干脆把这题丢到一边,想其他题,后来又过了一题以后就继续这题,因为题目要求的数据范围是1~10^18,用longlong不会爆,而且这时才想起阶乘数的一个特征,相邻两项的差距是越来越大的,某一个数的前面所有数的和加起来也不够这个数大,于是就以这个为策略使用贪心算法,结果代码不长,然后wa了一次,检查发现是打表数字打错了,= =。后来听人家说这一题我们是做过的,所以其他人才过的这么快,= =。看来以后做完题目要总结一下。

    上代码:

     1 #include <stdio.h>
     2 #include <string.h>
     3 #include <map>
     4 #define MAX 10000
     5 using namespace std;
     6 
     7 long long p[21]={1,1,2,6,24,120,720,5040,40320,362880,3628800,39916800,479001600,6227020800,87178291200,1307674368000,20922789888000,355687428096000,6402373705728000,121645100408832000,2432902008176640000};
     8 bool mark[21];
     9 
    10 bool check(long long n,int q)
    11 {
    12     if(n==0) return 1;
    13     int i;
    14     for(i=q;i>=0;i--)
    15     {
    16         if(n>=p[i]) break;
    17     }
    18     q=i;
    19     if(mark[q]) return 0;
    20     mark[q]=1;
    21     if(check(n-p[q],q-1)) return 1;
    22     mark[q]=0;
    23     return 0;
    24 }
    25 
    26 
    27 
    28 
    29 int main()
    30 {
    31     //freopen("data.txt","r",stdin);
    32     int i,j,t,c;
    33     long long n;
    34     scanf("%d",&t);
    35     for(i=1;i<=t;i++)
    36     {
    37         scanf("%lld",&n);
    38         memset(mark,0,sizeof(mark));
    39         printf("Case %d: ",i);
    40         if(!check(n,20)) printf("impossible
    ");
    41         else
    42         {
    43             c=0;
    44             for(j=0;j<=20;j++)
    45             {
    46                 if(mark[j])
    47                 {
    48                     if(c++) printf("+");
    49                     printf("%d!",j);
    50                 }
    51             }
    52             printf("
    ");
    53         }
    54     }
    55 
    56     return 0;
    57 }
    1189
  • 相关阅读:
    实用的网站记录
    XML记一次带命名空间的xml读取
    WEB项目挂载到IIS session过期
    【EF】CodeFirst Fluent API使用记录
    【Unity】微软的一款依赖注入组件
    【AutoFac】依赖注入和控制反转的使用
    【JavaScript】封装实用方法【持续积累】
    【Config】类库读取自己的配置文件,配置文件的扩展
    【c#】队列(Queue)和MSMQ(消息队列)的基础使用
    0、Java配置----JDK开发环境搭建及环境变量配置
  • 原文地址:https://www.cnblogs.com/sineatos/p/3221476.html
Copyright © 2011-2022 走看看