bzoj 4521: [Cqoi2016]手机号码

来源:互联网 发布:樱井翔堀北真希 知乎 编辑:程序博客网 时间:2024/05/20 20:17
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
原创粉丝点击