题意:给你一个字符串,分别表示0-9的状态。求一个四位密码的组合有多少种。
O:表示密码一定有该数字。
X:表示密码一定没有该数字。
?:不确定密码里有没有,可能有可能没有,
思路:
按密码含几个数字的角度思考:
只由一个数字:1
只由两个数字:14 (4位2进制分别减去0000和1111两种情况)
只由三个数字:36 (肯定有一个数字出现两次,先放这个数字C(4,2),这个数字有3种可能;再放另外两个数字,一共两种可能)
只由四个数字:24 (4!)
cpp
void solve()
{
cin>>s;
ll o=0,x=0,y=0;
for(int i=0;i<s.size();i++)
{
if(s[i]=='o')o++;
else if(s[i]=='?')x++;
else y++;
}
if(o==0)ans=x+14*x*(x-1)/2+6*x*(x-1)*(x-2)+x*(x-1)*(x-2)*(x-3);//别忘记惹
if(o==1)ans=1+x*14+36*x*(x-1)/2+x*(x-1)*(x-2)/6*24;
if(o==2)ans=14+36*x+24*x*(x-1)/2;
if(o==3)ans=36+24*x;
if(o==4)ans=24;
cout<<ans;
}
思路:溢水法,一开始把所有的牌放到最小的,一直往大数上溢,不能溢了就停止。
cpp
例如:
n=3,k=13
a0=0,a1=1,a2=3;
f(s)=14的s是答案。
i: 0 1 2
钱:1 10 100
k: 14 0 0
溢: 9 5 0
ans=9*1+5*10=59
cpp
void solve()
{
cin>>n>>k;
for(int i=0;i<n;i++)cin>>b[i],a[i]=0;
sort(b,b+n);
k++;
a[0]=k;
for(int i=1;i<n;i++)
{
ll now=pow(10ll,b[i]);
ll last=pow(10ll,b[i-1]);
ll res=last*a[i-1]/now;
if(res>0)
{
ll tmp=now/last-1;
a[i]=a[i-1]-tmp;
a[i-1]=tmp;
}
else break;
}
ans=0;
for(int i=0;i<n;i++)
{
ans+=a[i]*(ll)pow(10ll,b[i]);
}
cout<<ans<<'\n';
}