荔枝丹(litchi)
荔枝丹(litchi)
题目描述
绛雪艳浮红锦烂,玉壶光莹水晶寒。
高名已许传新曲,芳味曾经荐大官。
乌府日长霜署静,几株斜覆石栏杆。
——明·陈辉《荔枝》
荔枝(丹),拼音为lizhidan,一种好吃的水果,深得悦色老师的喜爱。
祝阿姨得到了许多许多的荔枝丹,每个荔枝丹上都有一个00到99之间的数字。祝阿姨把它们分成许多组,每组表示一个数,且所有组表示的数字合起来恰好是[L,R][L,R]内的所有数。
祝阿姨知道悦色老师特别喜欢吃荔枝丹,于是邀请了悦色老师来吃荔枝丹。悦色老师最喜欢吃有数字00的荔枝丹了,她吃掉了所有数字为00的荔枝丹。
祝阿姨想知道还剩下多少不同的组。注意悦色老师吃完后,荔枝丹就无序了,也就是说123123和321321是同样的组。
输入
一行两个正整数L,RL,R。
输出
一行一个整数,表示还剩下多少不同的组。
样例输入
<span style="color:#333333"><span style="color:#333333">【样例1输入】
1 10
【样例2输入】
40 57
【样例3输入】
157 165
</span></span>
样例输出
<span style="color:#333333"><span style="color:#333333">【样例1输出】
9
【样例2输出】
17
【样例3输出】
9</span></span>
提示
【子任务】
测试点 |
R |
R-L |
1~2 |
≤106 |
≥0 |
3~4 |
≤1018 |
0≤R-L≤1000000 |
5~20 |
≥0 |
来源
solution
首先由18位的不同数码(无序)的数量为
C(27,9)约=4e6
所以我们可以枚举所有可能的数码,然后判断这个数码能否在[l,r]中出现
用go(pos,l_flag,r_flag),表示到了第pos位,当前获得的数字是否等于相应的L/R的前缀,返回当前枚举的字符串能否构造出来。
分类讨论:
如果pos == n,则返回true。
如果l_flag == 1 && r_flag == 1,进一步讨论:
如果L[pos] == R[pos],则在第pos位只能是L[pos],然后进行go(pos+1, 1, 1);
如果L[pos]<R[pos],那么如果可以放[L[pos]+1,R[pos]-1]中的数字,那么一定可行;如果不可以,则尝试放L[pos]并继续go(pos+1,1,0)或放R[pos]并继续go(pos+1,0,1)。
如果l_flag和r_flag有且仅有一个为真,则与上面的讨论类似,先考虑把那个卡边界的弄成不卡的,如果可行直接返回真,不可行就继续卡边界继续枚举。
#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<cmath>
#define ll long long
using namespace std;
ll l,r,L[20],R[20],ans,num[20],f[10];
bool pd(int k,int fl,int fr){
//cout<<k<<' '<<fl<<' '<<fr<<endl;
if(k==19)return 1;
if(fl==0&&fr==0)return 1;
if(fl==1&&fr==1){
if(L[k]==R[k]){
if(f[L[k]]){
f[L[k]]--;int t=pd(k+1,1,1);f[L[k]]++;
return t;
}
else return 0;
}
if(L[k]<R[k]){
for(int i=L[k]+1;i<R[k];i++)if(f[i])return 1;
bool can=0;
if(f[L[k]]){
f[L[k]]--;can|=pd(k+1,1,0);f[L[k]]++;
}
if(can)return 1;
if(f[R[k]]){
f[R[k]]--;can|=pd(k+1,0,1);f[R[k]]++;
}
return can;
}
if(L[k]>R[k])return 0;
}
if(fl==1){
for(int i=L[k]+1;i<=9;i++)if(f[i])return 1;
if(f[L[k]]){
f[L[k]]--;int t=pd(k+1,1,0);f[L[k]]++;
return t;
}
return 0;
}
if(fr==1){
for(int i=R[k]-1;i>=0;i--)if(f[i])return 1;
if(f[R[k]]){
f[R[k]]--;int t=pd(k+1,0,1);f[R[k]]++;
return t;
}
return 0;
}
}
void dfs(int k){
//cout<<k<<endl;
if(k==19){
for(int i=0;i<=10;i++)f[i]=0;
for(int i=1;i<=18;i++)f[num[i]]++;
//for(int i=0;i<=9;i++)cout<<f[i]<<' ';cout<<endl;
//for(int i=1;i<=18;i++)cout<<num[i];cout<<endl;
if(pd(1,1,1))ans++;
return;
}
for(int i=num[k-1];i<=9;i++){
num[k]=i,dfs(k+1);
}
}
int main(){
cin>>l>>r;
if(r==(ll)1e18){
if(l<=(ll)1e17)r--;
else r--,ans++;
}
int top=18;
for(top=18;top>0;top--)L[top]=l%10,l/=10;
for(top=18;top>0;top--)R[top]=r%10,r/=10;
//for(int i=1;i<=18;i++)cout<<L[i];cout<<endl;
//for(int i=1;i<=18;i++)cout<<R[i];cout<<endl;
dfs(1);
cout<<ans<<endl;
return 0;
}