数位dp

不要62

dfs版本:

#include <cstdio>
#include <deque>
#include <set>
#include <string>
#include <map>
#include <vector>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <cmath>
#include <queue>
using namespace std;
typedef long long LL;

/*
int dfs(int i, int s, bool e) {
    if (i==-1) return s==taret_s;
    if (!e && ~f[i][s]) return f[i][s];
    int res = 0;
    int u = e?num[i]:9;
    for (int d = first?1:0; d <= u; ++d)
        res += dfs(i-1, new_s(s, d), e&&d==u);
    return e?res:f[i][s]=res;
}
*/

int digit[11];
int dp[11][1000005];

int dfs(int i,int s,bool e){
	//printf("%d %d %d\n",i,s,e);
	if(i == -1)return 1;
	if(!e && ~dp[i][s]) return dp[i][s];
	int ans = 0;
	int u = e ? digit[i] : 9;
	for(int d=0;d<=u;d++){
		if(s % 10 == 6 && d == 2)continue;
		if(d == 4)continue;
		ans += dfs(i-1,s*10+d,e && d == u);
	}
	return e ? ans : dp[i][s] = ans;
}

void init(){
	memset(dp,-1,sizeof(dp));
}

int solve(int x){
	int pos = 0;
	while(x){
		digit[pos++] = x % 10;
		x /= 10;
	}
	return dfs(pos-1,0,1);
}

int main(){
	int n,m;
	init();
	solve(1);
	while(scanf("%d%d",&n,&m),n || m){
		int ans = solve(m) - solve(n-1);
		printf("%d\n",ans);
	}
	return 0;
}


不要13

#include <cstdio>
#include <deque>
#include <set>
#include <string>
#include <map>
#include <vector>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <cmath>
#include <queue>
using namespace std;
typedef unsigned long long LL;
#define Debug(x) (cerr << #x << " = " << (x) << endl)
#define Debug2(x, y) (cerr << #x << " = " << (x) << ", " << #y << " = " << (y) << endl)
template<class T> inline T& RD(T &x){  
    char c; for (c = getchar(); c < '0'; c = getchar()); x = c - '0'; for (c = getchar(); '0' <= c && c <= '9'; c = getchar()) x = x * 10 + c - '0';  
    return x;  
}

/* WA ,开始时是找到就返回,没想到一个数可以对应多个值,要取最小的;还有如果发现LL变负,不管三七二十一先全变成LL 乱搞 */


/*
int fuck[20][2];//fuck[i][0] 表示长度为i,以1结尾的不含13的个数 fuck[i][1]表示其他的个数

void init(){
	memset(fuck,0,sizeof(fuck));
	fuck[0][0] = 0;
	fuck[0][1] = 1;//?
	for(int i=1;i<19;i++){
		fuck[i][0] = fuck[i-1][1] + fuck[i-1][0];
		fuck[i][1] = fuck[i-1][1]*10 + fuck[i-1][0]*9;
	}
}
*/


LL digit[40];
LL fuck[40][10];
LL dfs(int i,int isone,bool e){
	if(i == -1)return 1;
	if(!e && ~fuck[i][isone]) return fuck[i][isone];
	LL ans = 0;
	int u = e ? digit[i] : 9;
	for(int d=0;d<=u;d++){
		if(isone == 1 && d == 3)continue;
		ans += dfs(i-1,d,e && d==u);
	}
	//Debug2(i,ans);
	//if(ans < 0)Debug2(i,ans);
	return e ? ans : fuck[i][isone] = ans;
}

void init(){
	memset(fuck,-1,sizeof(fuck));
}

LL solve(LL x){
	int pos = 0;
	while(x){
		digit[pos++] = x % 10;
		x /= 10;
	}
	return dfs(pos-1,0,1)-1;
}


LL binarysearch(LL x){
	LL l = 0,r = 1ULL<<63ULL-1,mid,ans;
	while(l <= r){
		mid = (l+r) >> 1;
		LL m = solve(mid);
		if(m >= x){//return mid;
			ans = mid;
			r = mid - 1;
		}
		//else if(m > x)r = mid - 1;
		else l = mid + 1;
	}
	return ans;	
}


int main(){
	LL n;
	int T;
	init();
	scanf("%d",&T);
	while(T --){
		scanf("%lld",&n);
		LL ans = binarysearch(n);
		cout << ans << endl;
		//printf("%lld\n",ans);
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值