数位dp(洛谷 P4124 [CQOI2016]手机号码)
作者:互联网
题目链接
普通数位dp,不过有几点值得深思。
首先,我们每个手机号的位数固定为11位,即,不满足11位的并不是手机号不满足条件。而且如果像普通数位dp那样求该数到0之间的数量的话,还要考虑前导0的印象。(多开一维数组存前导0)不太值得。所以,我们直接求该数到1e10之间的数:
int mx = flag?su[cur]:9;
int bon = (cur==len-1)?1:0;
ll ans = 0;
for (int i = bon; i<=mx; i++)
{
//...........
}
此后我们设:
dp[i][p1][p2][sg1][sg2] 为考虑前i位,最后一个数字为p2,倒数第二个数字为p1,已有三个连续数相等(sg1==1)、没有三个连续数相等(sg1 ==0)的情况。其中8、4存在的情况由sg2决定:
sg2 == 0 无4、无8
sg2 == 1 有4、无8
sg2 == 2 无4、有8
sg2 == 3 有4、有8
然后就是标准数位dp过程
下面是ac代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <string>
#include <algorithm>
#include <cstdlib>
#include <queue>
#include <map>
#include <vector>
#define ll long long
using namespace std;
int dp[20][11][11][5][5];
int su[20];
int len;
ll dfs(int cur, int pre1, int pre2, int sg1, int sg2, bool flag)
{
//cout << cur << " " << pre1 << " " << pre2 <<" " << sg1 << " " <<sg2 << endl;
if (cur < 0)
return sg1 && sg2 != 3;
if (!flag&&dp[cur][pre1][pre2][sg1][sg2] != -1) return dp[cur][pre1][pre2][sg1][sg2];
int mx = flag?su[cur]:9;
int bon = (cur==len-1)?1:0;
ll ans = 0;
// cout << bon <<" " << mx << endl;
for (int i = bon; i<=mx; i++)
{
int nowsg2;
if (i == 4)
{
if (sg2 == 0) nowsg2 = 1;
else if (sg2 == 1) nowsg2 = 1;
else if (sg2 == 2) nowsg2 = 3;
else nowsg2 = 3;
}
else if (i == 8)
{
if (sg2 == 0) nowsg2 = 2;
else if (sg2 == 1) nowsg2 = 3;
else if (sg2 == 2) nowsg2 = 2;
else nowsg2 = 3;
}
else nowsg2 = sg2;//找当前sg2
int nowsg1;
if (sg1 == 1) nowsg1 = 1;
else
{
if (cur == len-1 || cur == len-2) nowsg1 = 0;
else
{
if (i == pre1 && i == pre2) nowsg1 = 1;
else nowsg1 = 0;
}
}//找当前sg1
ans += dfs(cur-1, pre2, i, nowsg1, nowsg2, flag&&i==mx);//转移
}
if (!flag) dp[cur][pre1][pre2][sg1][sg2] = ans;
return ans;
}
ll so(ll n)
{
len = 0;
while(n)
{
su[len++] = n%10;
n /= 10;
}
if (len != 11) return 0;//注意特判,因为这里wa了一发,因为l-1可能是9999999999.
return dfs(len-1, 0, 0, 0, 0, 1);
}
int main()
{
ll r, l;
scanf("%lld%lld", &l, &r);
memset(dp, -1, sizeof(dp));
ll ansr = so(r);
ll ansl = so(l-1);
printf("%lld\n", ansr - ansl);
}
标签:11,CQOI2016,洛谷,int,sg2,sg1,include,dp 来源: https://blog.csdn.net/qq_35802619/article/details/99698441