题目描述
链接:https://ac.nowcoder.com/acm/contest/120561/A 来源:牛客网
小苯正在学习 A+B Problem,为此他从家中翻出了恰好八个"七段码数位显示器"(以下简称显示器)。
如下图所示,显示器共有 7 个灯管,图中已标明编号。点亮其中的一些灯管就可以形成合法的数字, 0 − 9的对应的点亮结果如下图二,其中红色灯管是被点亮的,灰色则是未被点亮(其余的结果均是不合法的数字)。
遗憾的是,放置时间太久导致所有的显示器都发生了相同的故障,具体来说,在点亮他们的编号为 i 的灯管时,灯管都是仅有 𝑝 𝑖 % 的概率会被点亮,而还会有 100 % − 𝑝 𝑖 % 的概率不会被点亮(各根灯管的点亮尝试相互独立;不同显示器之间、同一显示器内不同编号灯管之间的点亮结果均互不影响)。 但小苯的学习还得进行下去,现在他会让小红指定一个整数 C ( 0 ≦ C ≦ 2026 ),接着小苯会将其中的四个排成一排,另外四个排成另一排,并对其 7 根灯管(共 7 × 8等于 56)均各尝试一次点亮操作。(由于所有显示器参数相同,具体选哪 4 台放在第一排与第二排均等价,可视为任意固定分配)。
现在请你计算出如下事件的概率(需全部满足): 最终所有显示器均有灯管被点亮(也就是说显示器的灯管不能全灭)。 最终所有显示器显示的结果均为合法数字。
第一排的显示器前后拼接形成的四位十进制数记作 A,第二排的显示器前后拼接形成的四位十进制数记作 B 的话,满足: A + B 等于 C(两排显示器从左到右依次作为千位、百位、十位、个位进行拼接,可以存在前导 0 )。
题解如下:
首先存储每一根灯管点亮的概率,而计算每一个数字被表达出来的概率,可以通过状态压缩,更方便计算,计算每个数字被表现出来的概率时,应注意,比如0,要计算123567灯管点亮的概率乘上4灯管点不亮的概率,同时在过程中通过逆元的方式取模避免溢出。之后暴力扫一遍A+B=C的可能情况,过程同样需要取模,最后将每一对A+B=C的概率相加并取模可得最后答案。 下附代码:
using namespace std;
typedef long long int ll;
ll ksm(ll x, ll y) {
ll res = 1;
while (y) {
if(y & 1) res = res * x % mod;
y >>= 1;
x = x * x % mod;
}
return res;
}
ll inv(ll x) {
return ksm(x, mod - 2);
}
void G(vector<ll>&num,vector<ll>&vt)
{
ll inv100=inv(100);
ll bb[10]={1110111,100100,1011101,1101101,101110,1101011,1111011,100101,1111111,1101111};
for(ll i=0;i<10;i++)//注意存储0~9状态时,如果用整型存储不要用0开头否则会被识别成8进制,警示后人
{
ll digit=bb[i];
for(ll j=0;j<7;j++)
{
if(digit%10==1)
vt[i]=vt[i]*(num[j]*inv100%mod)%mod;
else vt[i]=vt[i]*((100-num[j])*inv100%mod)%mod;
digit/=10;
}
// cout<<vt[i]<<endl;
}
}
void solve()
{
ll C,ans=0;
cin>>C;
vector<ll>num(7);
vector<ll>vt(10,1);
for(ll i=0;i<7;i++)
cin>>num[i];
G(num,vt);
for(ll i=0;i<=C;i++)
{
ll nub1=i,nub2=C-i,prob=1;
for(ll k=0;k<4;k++)
{
prob=prob*vt[nub1%10]%mod;
prob=prob*vt[nub2%10]%mod;
nub1/=10;
nub2/=10;
}
ans=(ans+prob)%mod;
}
cout<<ans<<endl;
}
如有错误烦请指正谢谢

京公网安备 11010502036488号