您的位置:首页 > 其它

数位dp 等凹数字 (未完成)

2017-03-27 19:45 253 查看
广工校赛

Problem G: 等凹数字

Description

定义一种数字称为等凹数字,即从高位到地位,每一位的数字先非递增再非递减,不能全部数字一样,且该数是一个回文数,即从左读到右与从右读到左是一样的,仅形成一个等凹峰,如543212345,5544334455是合法的等凹数字,543212346,123321,111111不是等凹数字。现在问你[L,R]中有多少等凹数字呢?

Input

第一行一个整数T,表示数据的组数。

接下来T行每行俩个数字L和R,(1<=L<=R<=1e18)

Output

输出一个整数,代表[L,R]中有多少等凹数字

Sample Input

2

1 100

101 200

Sample Output

0

1

HINT

小于等于2位的数字无凹峰

//太坑了,只会套模板,这个地方不知道怎么修改成”凹峰“会错。

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<string>
#include<cstring>
#include<iomanip>
#include<iostream>
#include<stack>
#include<cmath>
#include<map>
#include<vector>
#define ll long long
#define inf 0x3f3f3f3f
#define bug1 cout<<"bug1"<<endl;
#define bug2 cout<<"bug2"<<endl;
#define bug3 cout<<"bug3"<<endl;
using namespace std;
int dig[30];
int tmp[30];
int dp[30][30][2];
int dfs(int pos,int start,int flag,bool limit){
if(pos<0){
int flagsame=1;
for(int i=1;i<=start;++i){
if(tmp[i]!=tmp[i-1]){
flagsame=0;break;
}
}

if(flagsame||flagup)return 0;
else return flag;

}
if(!limit&&dp[start][pos][flag]!=-1)return dp[start][pos][flag];
int up=limit?dig[pos]:9;
int ret=0;
for(int i=0;i<=up;++i){
/*
if(pos>=(1+start)/2){
int flagde=0;
for(int j=start;j>=pos;--j){
if(tmp[j]<i){
flagde=1;break;
}
}
if(flagde)continue;
}
bug1
*/
tmp[pos]=i;
if(start==pos&&i==0){
ret+=dfs(pos-1,start-1,flag,limit&&dig[pos]==i);
}
else if(flag==1&&pos<(1+start)/2){
ret+=dfs(pos-1,start,tmp[pos]==tmp[start-pos],limit&&dig[pos]==i);
}
else{
ret+=dfs(pos-1,start,flag,limit&&dig[pos]==i);
}
}
if(!limit)dp[start][pos][flag]=ret;
return ret;
}
int solve(ll x){
memset(dig,0,sizeof(dig));
int tol=0;
while(x){
dig[tol++]=x%10;
x/=10;
}
return dfs(tol-1,tol-1,1,true);
}
int main(){
int t;
scanf("%d",&t);
int _case=0;
memset(dp,-1,sizeof(dp));
solve(1e18);
while(t--){
ll a,b;
scanf("%lld%lld",&a,&b);
if(a>b)swap(a,b);
printf("Case %d: %d\n",++_case,solve(b)-solve(a-1));
}
}


标程,,还没看2017年3月31日13:20:38
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <time.h>
#include <set>
#include <map>
#include <string>
#include <math.h>
#include <stdlib.h>
using namespace std;
long long dp[20][20][10][2][2][2];
int num[20];
int s[20];
long long rec(int i,int pre,int up,int down,int flag,int q,int len,int ispa)
{
if(i<0)return up&&down&&ispa;
if(~dp[i][len][pre][up][down][ispa]&&!flag&&!q)return dp[i][len][pre][up][down][ispa];
long long res=0;
int o=s[i];
for(int j=0;j<10;j++)
{
num[i]=j;
if(j>o&&flag)break;
if(q)res+=rec(i-1,j,0,0,j<o?0:flag,q&&j==0,len-(q&&j==0),ispa);
else if(j==pre)
{
if(ispa&&i<len/2)
res+=rec(i-1,j,up,down,j<o?0:flag,q&&j==0,len,j==num[len-i-1]);
else res+=rec(i-1,j,up,down,j<o?0:flag,q&&j==0,len,ispa);
}
else if(j>pre)
{
if(!down)continue;
if(ispa&&i<len/2)
res+=rec(i-1,j,1,down,j<o?0:flag,q&&j==0,len,j==num[len-i-1]);
else res+=rec(i-1,j,1,down,j<o?0:flag,q&&j==0,len,ispa);
}
else if(j<pre)
{
if(up)continue;
if(ispa&&i<len/2)
res+=rec(i-1,j,up,1,j<o?0:flag,q&&j==0,len,j==num[len-i-1]);
else res+=rec(i-1,j,up,1,j<o?0:flag,q&&j==0,len,ispa);
}
}
if(!flag&&!q)dp[i][len][pre][up][down][ispa]=res;
return res;
}
long long cal(long long x)
{
int len=0;
while(x)
{
s[len++]=x%10;
x/=10;
}
return rec(len-1,0,0,0,1,1,len,1);
}
int main()
{
memset(dp,-1,sizeof(dp));
long long l,r;
int t;
scanf("%d",&t);
while(t--){
scanf("%lld%lld",&l,&r);
printf("%lld\n",cal(r)-cal(l-1));
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: