Loading

7.20试机测 T3 阶乘之和 暴力AC题解

7.20试机测  T3 阶乘之和 暴力AC题解

题外话:此乃本蒟蒻发表的第一篇题解,大家多多关照,支持一下,谢谢


题面

3、阶乘之和(sum.pas/in/out)

问题描述: 给定一个非负整数 n,请你判断 n 是否可以由一些非负整数的阶乘相加得到。

问题输入: 有若干组数据。每行一个整数 n,保证 n<1000000。 以负数结束输入。

问题输出: 对于每组数据输出一行,若可以则输出‘YES’,否则输出‘NO’。

输入样例: 9 -1

样例输出: YES


分析

这个题嘛

大概了解了一下题意,就是给出n,判断n能不能被几个数的阶乘加起来。(虽然题目没有说清楚数字能不能重复,但是我们知道1的阶乘是1,如果数字可以重复的话,那么任何n都是YES了,所以我推测所选数字不能重复)


 

题目让输入多组数据,我们先针对一个数据进行操作,在结尾再弄关于输入多组数据的问题…………

下面算出一些较小数的阶乘(千万不要忘记0)(这一步可以在Excel完成,用FACT函数)

 

看到数据范围, n<1000000,可以了解到所选的数字应该在0~9里。

那么,n的最大值就确定了,即0~9的阶乘之和(1+1+2+6+24+...+40320+362880=409114)

 

也就是说,只要n的值超过了409114,那么这个n就不符合条件,可以提前判断一部分n是不是NO。

还有,0的阶乘是1,那么如果n的值为0,就没有非负整数满足n,也是直接NO。

if(n>409114 || n==0)
    cout<<"NO"<<endl;

 


 下面怎么办呢,暴力?!

在这里,我还没有学一些什么神奇01背包,二进制什么玩意……

我就简简单单地用几个for循环来搜出所有情况吧。

 

先开一个数组(第一个开0是防止有??的情况   其实第一个完全可以不开0,不开0还节省了时间)

long long x[11]= {0,1,1,2,6,24,120,720,5040,40320,362880};

 

我们知道,题目给定一个n,这个n可能由上面数组中的1个数相加得到,也可能是2个,也可能是多个……

(比如n=4时,n是1+1+2,由数组中的3个数相加得到;n=25时,则为1+24,由数组中的2个数相加得到)

 

那么,我们先假设n由上面选1个数得到,则可以

for(int a=0; a<11; ++a)
    if(x[a]==n)
    {
       cout<<"YES"<<endl;
    }

 

如果一个数不行,那就看看2个数加起来能不能得到n

这里防止有判重的情况,就让b=a+1,还节省了时间。

for(int a=0; a<11; ++a)
    for(int b=a+1; b<11; ++b)
        if(x[a]+x[b]==n)
        {
            cout<<"YES"<<endl;
        }

 

下面以此类推……直到10个数的时候

for(int a=0; a<11; ++a)
for(int b=a+1; b<11; ++b) for(int c=b+1; c<11; ++c) for(int d=c+1; d<11; ++d) for(int e=d+1; e<11; ++e) for(int f=e+1; f<11; ++f) for(int g=f+1; g<11; ++g) for(int h=g+1; h<11; ++h) for(int i=h+1; i<11; ++i) for(int j=i+1; j<11; ++j) if(x[a]+x[b]+x[c]+x[d]+x[e]+x[f]+x[g]+x[h]+x[i]+x[j]==n) { cout<<"YES"<<endl; }

 

这样就行了?此处忽略了一个地方,假设n由5个数相加就能得到,那么下面的6次,7次循环再执行岂不是浪费掉了时间嘛。

所以,我们开一个布尔变量,用来判断n是不是已经被配对

bool yes=false;

 


 

好了,现在我们可以研究输入多组数据的问题了,因为不研究这个,布尔变量就没法展现它的作用。

题意说输入负数的时候结束程序(千万不要被样例迷惑了,不一定是-1结束程序)

那么,可以用while循环输入数据。

每输入一个n,就对n执行一次下面的操作。 直到n<0时,return 0 结束程序。

<0

int main()
{
    while(scanf("%d",n) && n>=0)
    {
        yes=false;
        //此处往下写程序,每次当n配对时,把布尔变量变成true。
    }
  return 0; }

 

当n被配对时,变量yes的值为true。我们可以在程序中疯狂检测 yes的值,只要是true就立即让它输出“YES”,然后扔掉此时的n,再对下一个数字n进行操作。

 

具体操作如下(拿n由4个数相加得到 举例):

        for(int a=0; a<11; ++a)
        {
            for(int b=a+1; b<11; ++b)
            {
                for(int c=b+1; c<11; ++c)
                {
                    for(int d=c+1; d<11; ++d)
                        if(x[a]+x[b]+x[c]+x[d]==n)
                        {
                            cout<<"YES"<<endl;
                            yes=true; //只要n被配对成功,就把布尔设为true
                            break;
                        }
                    if(yes==true) break;   //让被配对成功的n 一路顺风,跳出循环
                }
                if(yes==true) break;  
            }
            if(yes==true) break;
        }

     if(yes==true) continue;  //此时的 continue 与 while 读入操作在同一层。这样就可以读入下一个n了

 

这样看起来好像有点麻烦,但是我觉得理解起来不难吧qwq.

 

最后当10次循环都走一遍,结果n没有找到合适的数字,就在末尾输出“NO”.

 


AC代码:

  1 /*---------------------------------
  2  *Title number:  7.20 试机测 T3 阶乘之和 
  3  *Creation date: 2020-07-20 afternoon
  4  *By: EdisonBa
  5  *-------------------------------*/
  6 #include<iostream>
  7 #include<cstdio>
  8 #include<cmath>
  9 #include<cstdlib>
 10 #include<cstring>
 11 #include<algorithm>
 12 using namespace std;
 13 
 14 long long x[11]= {0,1,1,2,6,24,120,720,5040,40320,362880};
 15 long long n;
 16 bool yes=false;
 17 
 18 int main()
 19 {
 20     while(cin>>n && n>=0)
 21     {
 22         yes=false;  //每一次对n操作都要重置一下布尔变量 yes 
 23         
24 //下面判一下最大值和0 25
26 if(n>409114 || n==0) 27 { 28 cout<<"NO"<<endl; 29 continue; 30 } 31
32 //下面进行第 1 次循环 33
34 for(int a=0; a<11; ++a) 35 if(x[a]==n) 36 { 37 cout<<"YES"<<endl; 38 yes=true; 39 break; 40 } 41 42 if(yes==true) continue; 43
44 //下面进行第 2 次循环 45
46 for(int a=0; a<11; ++a) 47 { 48 for(int b=a+1; b<11; ++b) 49 50 if(x[a]+x[b]==n) 51 { 52 cout<<"YES"<<endl; 53 yes=true; 54 break; 55 } 56 if(yes==true) break; 57 } 58 59 if(yes==true) continue; 60
61 //下面进行第 3 次循环 62
63 for(int a=0; a<11; ++a) 64 { 65 for(int b=a+1; b<11; ++b) 66 { 67 for(int c=b+1; c<11; ++c) 68 69 if(x[a]+x[b]+x[c]==n) 70 { 71 cout<<"YES"<<endl; 72 yes=true; 73 break; 74 } 75 if(yes==true) break; 76 } 77 if(yes==true) break; 78 } 79 80 if(yes==true) continue; 81
82 //下面进行第 4 次循环 83
84 for(int a=0; a<11; ++a) 85 { 86 for(int b=a+1; b<11; ++b) 87 { 88 for(int c=b+1; c<11; ++c) 89 { 90 for(int d=c+1; d<11; ++d) 91 if(x[a]+x[b]+x[c]+x[d]==n) 92 { 93 cout<<"YES"<<endl; 94 yes=true; 95 break; 96 } 97 if(yes==true) break; 98 } 99 if(yes==true) break; 100 } 101 if(yes==true) break; 102 } 103 104 if(yes==true) continue; 105
106 //下面进行第 5 次循环 107
108 for(int a=0; a<11; ++a) 109 { 110 for(int b=a+1; b<11; ++b) 111 { 112 for(int c=b+1; c<11; ++c) 113 { 114 for(int d=c+1; d<11; ++d) 115 { 116 for(int e=d+1; e<11; ++e) 117 if(x[a]+x[b]+x[c]+x[d]+x[e]==n) 118 { 119 cout<<"YES"<<endl; 120 yes=true; 121 break; 122 } 123 if(yes==true) break; 124 } 125 if(yes==true) break; 126 } 127 if(yes==true) break; 128 } 129 if(yes==true) break; 130 } 131 132 133 if(yes==true) continue; 134
135 //下面进行第 6 次循环 136
137 for(int a=0; a<11; ++a) 138 { 139 for(int b=a+1; b<11; ++b) 140 { 141 for(int c=b+1; c<11; ++c) 142 { 143 for(int d=c+1; d<11; ++d) 144 { 145 for(int e=d+1; e<11; ++e) 146 { 147 for(int f=e+1; f<11; ++f) 148 if(x[a]+x[b]+x[c]+x[d]+x[e]+x[f]==n) 149 { 150 cout<<"YES"<<endl; 151 yes=true; 152 break; 153 } 154 if(yes==true) break; 155 } 156 if(yes==true) break; 157 } 158 if(yes==true) break; 159 } 160 if(yes==true) break; 161 } 162 if(yes==true) break; 163 } 164 165 if(yes==true) continue; 166
167 //下面进行第 7 次循环 168
169 for(int a=0; a<11; ++a) 170 { 171 for(int b=a+1; b<11; ++b) 172 { 173 for(int c=b+1; c<11; ++c) 174 { 175 for(int d=c+1; d<11; ++d) 176 { 177 for(int e=d+1; e<11; ++e) 178 { 179 for(int f=e+1; f<11; ++f) 180 { 181 for(int g=f+1; g<11; ++g) 182 if(x[a]+x[b]+x[c]+x[d]+x[e]+x[f]+x[g]==n) 183 { 184 cout<<"YES"<<endl; 185 yes=true; 186 break; 187 } 188 if(yes==true) break; 189 } 190 if(yes==true) break; 191 } 192 if(yes==true) break; 193 } 194 if(yes==true) break; 195 } 196 if(yes==true) break; 197 } 198 if(yes==true) break; 199 } 200 201 if(yes==true) continue; 202
203 //下面进行第 8 次循环 204
205 for(int a=0; a<11; ++a) 206 { 207 for(int b=a+1; b<11; ++b) 208 { 209 for(int c=b+1; c<11; ++c) 210 { 211 for(int d=c+1; d<11; ++d) 212 { 213 for(int e=d+1; e<11; ++e) 214 { 215 for(int f=e+1; f<11; ++f) 216 { 217 for(int g=f+1; g<11; ++g) 218 { 219 for(int h=g+1; h<11; ++h) 220 if(x[a]+x[b]+x[c]+x[d]+x[e]+x[f]+x[g]+x[h]==n) 221 { 222 cout<<"YES"<<endl; 223 yes=true; 224 break; 225 } 226 if(yes==true) break; 227 } 228 if(yes==true) break; 229 } 230 if(yes==true) break; 231 } 232 if(yes==true) break; 233 } 234 if(yes==true) break; 235 } 236 if(yes==true) break; 237 } 238 if(yes==true) break; 239 } 240 241 if(yes==true) continue; 242
243 //下面进行第 9 次循环 244
245 for(int a=0; a<11; ++a) 246 { 247 for(int b=a+1; b<11; ++b) 248 { 249 for(int c=b+1; c<11; ++c) 250 { 251 for(int d=c+1; d<11; ++d) 252 { 253 for(int e=d+1; e<11; ++e) 254 { 255 for(int f=e+1; f<11; ++f) 256 { 257 for(int g=f+1; g<11; ++g) 258 { 259 for(int h=g+1; h<11; ++h) 260 { 261 for(int i=h+1; i<11; ++i) 262 263 if(x[a]+x[b]+x[c]+x[d]+x[e]+x[f]+x[g]+x[h]+x[i]==n) 264 { 265 cout<<"YES"<<endl; 266 yes=true; 267 break; 268 } 269 if(yes==true) break; 270 } 271 if(yes==true) break; 272 } 273 if(yes==true) break; 274 } 275 if(yes==true) break; 276 } 277 if(yes==true) break; 278 } 279 if(yes==true) break; 280 } 281 if(yes==true) break; 282 } 283 if(yes==true) break; 284 } 285 286 if(yes==true) continue; 287
288 //下面进行第 10 次循环 289
290 for(int a=0; a<11; ++a) 291 { 292 for(int b=a+1; b<11; ++b) 293 { 294 for(int c=b+1; c<11; ++c) 295 { 296 for(int d=c+1; d<11; ++d) 297 { 298 for(int e=d+1; e<11; ++e) 299 { 300 for(int f=e+1; f<11; ++f) 301 { 302 for(int g=f+1; g<11; ++g) 303 { 304 for(int h=g+1; h<11; ++h) 305 { 306 for(int i=h+1; i<11; ++i) 307 { 308 for(int j=i+1; j<11; ++j) 309 if(x[a]+x[b]+x[c]+x[d]+x[e]+x[f]+x[g]+x[h]+x[i]+x[j]==n) 310 { 311 cout<<"YES"<<endl; 312 yes=true; 313 break; 314 } 315 if(yes==true) break; 316 } 317 if(yes==true) break; 318 } 319 if(yes==true) break; 320 } 321 if(yes==true) break; 322 } 323 if(yes==true) break; 324 } 325 if(yes==true) break; 326 } 327 if(yes==true) break; 328 } 329 if(yes==true) break; 330 } 331 if(yes==true) break; 332 } 333 334 if(yes==true) continue; 335
336 // 10次循环完毕,若n没有合适的数字,输出"NO" 337 338 cout<<"NO"<<endl; 339 340 } 341 342 return 0; 343 }

 

 https://www.luogu.com.cn/record/35414283

 

 

(此代码对于 第10个毒瘤点来说 能过就是奇迹)


 

这份代码,显然不是最优解(第10个测试点的时间快要爆了),如果把x数组里的0删去,可能时间会稍微短那么几毫秒。

但是这个理解起来很容易,只要有充足的时间就能写出来(大概半个多小时)。

我觉得这个代码的关键就是在每次大循环中,下层的for的变量值是上层的变量值+1(无法表述啊这)

-----------------------------------------------------------------------------------------------------------------------------------------------

看图:

 

 -----------------------------------------------------------------------------------------------------------------------------------------------

这样节省了大部分时间,也防止出现了判重的情况,使得多次大循环顺利过测试点。


 感谢您观看此题解。

这是本蒟蒻发表的第一篇题解,岂不妙哉?!

希望在接下来的时间里,大家共同成长,共同进步,多多交流,共创辉煌!

 

EdisonBa

2020/7/20

 

posted @ 2020-07-20 16:54  EdisonBa  阅读(395)  评论(8编辑  收藏  举报