杭电2089-不要62

原题链接
在这里插入图片描述

分析

就是一个区间内的数,有一定要求,去掉包含4和连续的62的数这个区间的数有多少个,按照正常方法应该是标准数位dp,另附一个投机取巧算法

数位dp方法

可看做数位dp模板

//数位dp 
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define endl "\n"
const int maxn = 1e6 + 5;
int a[20];//存下区间端点的每一位
int dp[10][2] ;

int dfs(int pos, int pre, int sta, bool limit ) {
	//当前位置,前一位是什么数,前一位是不是6,是否需要判断数位上界 
	
	if(pos == 0)  return 1;//个位都已经确定好了,终止条件
	
	//保证唯一dp,这里对limit的要求可以大量剪枝,limit=1的情况很少 
	if(!limit && dp[pos][sta] != -1) 
		return dp[pos][sta]; 
	int up = limit ? a[pos] : 9;
	int tmp = 0;
	for(int i = 0; i <= up; i++) {
		if(pre == 6 && i == 2) continue;//出现了62 
		if(i == 4) continue;//出现了4,跳过
		tmp += dfs(pos-1, i, i == 6, limit && i == a[pos]) ;
	}
	//计算结束,记录状态 ,对每个状态,只会计算一次 
	if(!limit) dp[pos][sta] = tmp;
	return tmp;
}

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

int main() {
	int n,m;
	memset(dp,-1,sizeof(dp));
	while(scanf("%d %d",&n,&m) != EOF && (n || m)) {
		printf("%d\n",solve(m) - solve(n-1));
	}
	return 0;
}

当做字符串处理

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int arr[1000001];
void f(){
    int i;
    for(i=1;i<=1000000;i++)
    {
        char str[10];
        itoa(i,str,10);
        if(strstr(str,"4")==NULL&&strstr(str,"62")==NULL)
            arr[i]=1;
        else
            arr[i]=0;
    }  
} 
int main()
{
    int i;
    f();
    int n,m; 
    while(~scanf("%d%d",&n,&m)&&(n||m))
    {
        int s=0;
        for(i=n;i<=m;i++)
            s+=arr[i];
        printf("%d\n",s);
    }
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
杭州电子科技大学在线评测系统(杭电OJ)中的目1000-1100是一系列编程,我将分别进行回答。 1000是一个简单的入门,要求计算两个整数的和。我们可以使用一个简单的算法,读取输入的两个整数,然后将它们相加,最后输出结果即可。 1001是一个稍微复杂一些的目,要求实现字符串的逆序输出。我们可以使用一个循环来逐个读取输入的字符,然后将这些字符存储在一个数组中。最后,我们可以倒序遍历数组并将字符依次输出,实现字符串的逆序输出。 1002是一个求最大公约数的问。我们可以使用辗转相除法来解决,即先求出两个数的余数,然后将被除数更新为除数,将除数更新为余数,直至两个数的余数为0。最后的被除数就是最大公约数。 1003是一个比较简单的排序问。我们可以使用冒泡排序算法来解决,即每次比较相邻的两个元素,如果它们的顺序错误就交换它们的位置。重复这个过程直至整个数组有序。 1100是一个动态规划问,要求计算给定序列中的最长上升子序列的长度。我们可以使用一个数组dp来保存到达每个位置的最长上升子序列的长度。每当遍历到一个位置时,我们可以将其和之前的位置比较,如果比之前位置的值大,则将其更新为之前位置的值加1,最后返回dp数组的最大值即可。 以上是对杭电OJ1000-1100目的简要回答,涉及了一些基本的编程知识和算法思想。希望对您有所帮助。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值