bzoj 4521: [Cqoi2016]手机号码

f[i][j][012][k][s][d]表示前i位,开头为j,(有k-1位相同,是否已经出现3位相同), 出现48的状态为s,压位/不压位的方案数
由于11位不含前导0,不用写不足len位的dp
又写成 f[.....][i==a[i]]++ 应该是 f[....][i==a[1]]++
  
  
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
 
#define ll long long
#define inf 1e9
#define eps 1e-8
#define md
using namespace std;
int a[20],f[13][10][3][4][2];
int G(int k,int b)
{
if (k+b>=2) return 2;
if (!b) return 0;
else return k+1;
}
 
int S(int s,int b)
{
if (b==4) s|=1;
if (b==8) s|=2;
return s;
}
 
ll dp(ll x)
{
int len=0;
while (x) { a[++len]=x%10; x/=10;}
if (len<11) return 0;
memset(f,0,sizeof(f));
reverse(a+1,a+len+1);
for (int i=1;i<=a[1];i++) f[1][i][0][S(0,i)][i==a[1]]++;
for (int i=2;i<=len;i++)
{
for (int j=0;j<=9;j++)
for (int k=0;k<3;k++)
for (int s=0;s<3;s++)
{
if (f[i-1][j][k][s][0])
{
for (int b=0;b<=9;b++)
f[i][b][G(k,b==j)][S(s,b)][0]+=f[i-1][j][k][s][0];
}
if (f[i-1][j][k][s][1])
{
for (int b=0;b<=a[i];b++)
f[i][b][G(k,b==j)][S(s,b)][b==a[i]]+=f[i-1][j][k][s][1];
}
}
}
ll ans=0;
for (int j=0;j<=9;j++)
for (int s=0;s<3;s++)
ans+=f[len][j][2][s][0]+f[len][j][2][s][1];
return ans;
}
 
int main()
{
ll L,R;
scanf("%lld%lld",&L,&R);
printf("%lld\n",dp(R)-dp(L-1));
return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值