您的位置:首页 > 产品设计 > UI/UE

UESTC 1307 WINDY数 (数位DP,基础)

2015-10-02 20:06 405 查看
题意:

  windy定义了一种windy数。不含前导零且相邻两个数字之差至少为2的正整数被称为windy数。windy想知道,在A和B之间,包括A和B,总共有多少个windy数?

思路:

  就是给连续的两位数字之间一些限制而已。主要还是放在推数量的问题上。相信很容易能写出转移方程,但是本题的问题在于前导零问题,不知道你是如何统计开头为0的,比如dp[i][0]表示什么?如果就要统计区间[0,10],输出的dp[2][0]会是8吗?(即02,03,04,05,06,07,08,09),其实你忘记了统计00和01,因为他们和前导0冲突了。所以想办法解决这个问题就行了。

  由于本题找不到提交源头了,码出来不保证正确性。

//#include <bits/stdc++.h>
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <map>
#include <algorithm>
#include <vector>
#include <iostream>
#define pii pair<int,int>
#define INF 0x7f3f3f3f
#define LL long long
#define LL unsigned long long
using namespace std;
const double PI  = acos(-1.0);
const int N=10;
int dp

, sum
, bit[N+5];

void pre_cal()
{
sum[1]=10;
for(int i=0; i<N; i++) dp[1][i]=1;
for(int i=2; i<N; i++ ) //位数
{
sum[i]+=sum[i-1];
for(int j=1; j<N; j++)      sum[i]+=dp[i-1][j];//不含前导0
for(int j=0; j<N; j++)  //以j开头
{
for(int k=0; k<N; k++)  //下一个位以k开头
if(abs(j-k)>=2)
dp[i][j]+=dp[i-1][k];
}
}
}

int cal(int n)
{
memset(bit,0,sizeof(bit));
int len=0;
while(n)
{
bit[++len]=n%10;
n/=10;
}
int ans=sum[len-1], i=len;
for( ; i>0; i--)
{
for(int j=0; j<bit[i]; j++) //不能超过bit[i]
if( abs(bit[i+1]-j)>=2 )
ans+=dp[i][j];
if( i<len && abs(bit[i+1]-bit[i])<2 )
break;      //上一位和这位已经构成非法
}
if(i==0)    ans++;
return ans;
}

int main()
{
//freopen("input.txt","r",stdin);
pre_cal();
int L, R;
while(~scanf("%d%d",&L,&R))
printf("%d\n",cal(R)-cal(L-1));
return 0;
}


代码
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: