一、思路
题目中的公式有:
c
i
=
a
1
×
a
2
×
⋯
×
a
i
c_{i}=a_{1}\times a_{2}\times\cdots\times a_{i}
ci=a1×a2×⋯×ai
m = c 0 × b 1 + c 1 × b 2 + ⋯ + c n − 1 × b n m=c_{0}\times b_{1}+c_{1}\times b_{2}+\cdots+c_{n-1}\times b_{n} m=c0×b1+c1×b2+⋯+cn−1×bn
上述公式合并得到如下公式:
m
=
1
×
b
1
+
a
1
×
b
2
+
a
1
×
a
2
×
b
3
+
⋯
+
a
1
×
a
2
×
⋯
×
a
n
−
1
×
b
n
m=1\times b_{1}+a_{1}\times b_{2}+a_{1}\times a_{2}\times b_{3}+\cdots+a_{1}\times a_{2}\times\cdots\times a_{n-1}\times b_{n}
m=1×b1+a1×b2+a1×a2×b3+⋯+a1×a2×⋯×an−1×bn
其中题目说明了
c
0
=
1
c_{0}=1
c0=1,m为老师留下的神秘整数,
a
i
a_{i}
ai为第i道单项选择题的选项数目,
b
i
b_{i}
bi为第i道单项选择题的正确选项。
因此,若我们要求 b i b_{i} bi话,就需要知道m和 a i a_{i} ai,而输入格式里面包含有这两个数据。
接下来就需要找规律得到求 b i b_{i} bi的公式。
我们借助题目中给出的这个表格可以很容易推出规律来。
从上图可以看出
c
i
=
a
i
×
c
i
−
1
(
1
≤
i
≤
20
)
c_{i}=a_{i}\times c_{i-1}(1 ≤ i≤ 20)
ci=ai×ci−1(1≤i≤20)
c
i
c_{i}
ci可以求出来。
最后题目给了提示,通过这个公式我们就可以根据
c
i
c_{i}
ci求出
b
i
b_{i}
bi。我将公式转换了一下,如下:
m
m
o
d
c
i
=
m
m
o
d
c
i
−
1
+
c
i
−
1
×
b
i
m\bmod c_{i}=m \bmod c_{i-1}+c_{i-1}\times b_{i}
mmodci=mmodci−1+ci−1×bi
这样
b
i
b_{i}
bi也可以求出来了。
二、代码解读
-
为考试练手,这里就直接使用万能头文件
#include<bits/stdc++.h>
-
使用std命名空间
using namespace std;
-
定义变量
int n,m;//题目数量,神秘数字 int a[21];//选项数目 int b[21];//正确选项 int c[21];//辅助数组
-
由于 c 0 = 1 c_{0}=1 c0=1,这里就直接赋值。输入n题目数量和m神秘数字
c[0] = 1; cin>>n>>m;
-
为方便理解i直接从1开始,读取 a i a_{i} ai每个选项题选项个数,然后根据上面 c i = a i × c i − 1 ( 1 ≤ i ≤ 20 ) c_{i}=a_{i}\times c_{i-1}(1 ≤ i≤ 20) ci=ai×ci−1(1≤i≤20)这个公式求出 c i c_{i} ci,接下来根据 m m o d c i = m m o d c i − 1 + c i − 1 × b i m\bmod c_{i}=m \bmod c_{i-1}+c_{i-1}\times b_{i} mmodci=mmodci−1+ci−1×bi这个公式,变换一下,求出 b i b_{i} bi,最后直接输出。
for(int i=1;i<=n;i++){ cin>>a[i]; c[i]=a[i]*c[i-1]; b[i]=(m%c[i]-m%c[i-1])/c[i-1]; cout<<b[i]<<" "; }
这里标注一下:最开始我求 b i b_{i} bi的公式写的是
b[i]=(m%c[i])/c[i-1];
当时运行出来得到的答案是对的,后面提交上去也是正确的。但是后来写博客的时候发现我这个公式和前面用这个 m m o d c i = m m o d c i − 1 + c i − 1 × b i m\bmod c_{i}=m \bmod c_{i-1}+c_{i-1}\times b_{i} mmodci=mmodci−1+ci−1×bi公式推导的差了一步,没有 − m m o d c [ i − 1 ] -m\bmod c[i-1] −mmodc[i−1]。
使用的数据是题目给出的样例3,手动进行计算了一下。
例如b[2]的计算式子原本不进行减法的话是
b
[
2
]
=
(
23333
m
o
d
15
)
/
3
=
8
/
3
≈
2.666
\begin{equation} \begin{aligned} b[2] &= (23333\bmod15)/3 \\ &=8/3 \\ &\approx2.666 \end{aligned} \nonumber \end{equation}
b[2]=(23333mod15)/3=8/3≈2.666
但是由于这里我定义的变量和数组全部是int,所以最后b[2]不取后面的小数,直接就赋值为2。
若进行减法的话
b
[
2
]
=
(
23333
m
o
d
15
−
23333
m
o
d
3
)
/
3
=
(
8
−
2
)
/
3
=
2
\begin{equation} \begin{aligned} b[2] &= (23333\bmod15-23333\bmod3)/3 \\ &=(8-2)/3 \\ &=2 \end{aligned} \nonumber \end{equation}
b[2]=(23333mod15−23333mod3)/3=(8−2)/3=2
按照上面这个式子相减得到的结果就是一个整数。
后面几个b[3],b[4]等这些同样也是如果没有减上一个的取余,得到的结果就是一个小数,减了之后就是一个整数。
所以可以看出这次我第一次写的代码,虽然系统判定是对的,但是存在漏洞,若定义的不是int型,倘若是float浮点型就可以看出差距。第二次更改后的公式才是正确的。
-
由于考试对输出格式上有可能有要求,所以最后进行换行操作
cout<<endl;
三、完整代码
#include<bits/stdc++.h>
using namespace std;
int main()
{
int n,m;//题目数量,神秘数字
int a[21];//选项数目
int b[21];//正确选项
int c[21];//辅助数组
c[0] = 1;
cin>>n>>m;
for(int i=1;i<=n;i++){
cin>>a[i];
c[i]=a[i]*c[i-1];
b[i]=(m%c[i]-m%c[i-1])/c[i-1];
cout<<b[i]<<" ";
}
cout<<endl;
return 0;
}