Time Limit: 0.5 second(s) | Memory Limit: 32 MB |
Given an integer n, you have to find whether it canbe expressed as summation of factorials. For givenn, you have to reporta solution such that
n = x1!+ x2! + ... + xn! (xi < xj forall 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 insummation of factorial form. If there is no solution then print'impossible'.There can be multiple solutions, any valid one will do. See the samples forexact formatting.
Sample Input | Output for Sample Input |
4 7 7 9 11 | Case 1: 1!+3! Case 2: 0!+3! Case 3: 1!+2!+3! Case 4: impossible |
Note
Be careful about the output format; you may get wrong answerfor wrong output format.
第一思想肯定是枚举,然而可以非连续,,,DFS数据又很大,,,
除非找到阶乘的一个很重要的性质就是当前值的阶乘大于 小于他的数的阶乘和,这个规律,,不然很难会想到用贪心做因为无法判断所有情况,,,
数学+规律的推导技能
题意:N如果可以表示成某几个数的阶乘则找出这几个数,不能的话输出impossible,不能有x相同的的数;
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
typedef long long LL;
LL flag[30];
int ans[30];
int main()
{
flag[0]=flag[1]=1;
for(int i=2;i<=22;i++)
{
flag[i]=flag[i-1]*i;
}
int t, ncase=1;
scanf("%d", &t);
while(t--)
{
LL x;
scanf("%lld", &x);
for(int i=0;i<=22;i++)
{
if(x<flag[i])
{
printf("Case %d: impossible\n",ncase++);
break;
}
int cnt=0, res=0;
LL y=x;
for(int j=i;j>=0;j--)
{
if(y>=flag[j])
{
y-=flag[j];
ans[cnt++]=j;
}
if(y==0)
{
res=1;
printf("Case %d: %d!",ncase++,ans[cnt-1]);
for(int k=cnt-2;k>=0;k--)
{
printf("+%d!",ans[k]);
}
printf("\n");
break;
}
}
if(res==1)
{
break;
}
}
}
return 0;
}