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"<
下面怎么办呢,暴力?!
在这里,我还没有学一些什么神奇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 #include7 #include 8 #include 9 #include 10 #include 11 #include 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