ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

2657 windy数

2021-08-04 22:59:34  阅读:150  来源: 互联网

标签:int ll 2657 windy 位数 include SIZE


2657 windy数

啊,连了一天的动态规划,快给我整吐了,不过状压DP还没学,效率太低了,明天再用一天学完DP加上图论数据结构,然后拿出两整天的时间来学数论,如果济南夏令营还去的话,回来就备考初赛
数位dp的题,一般会给你l和r,求从l到r有多少个数满足某个性质
我们用f(i)表示前i位windy数的个数
那么答案就是f(r+1)-f(l)有点类似于区间DP
设f[i][j]表示位数位i最高位是j的windy数个数
方程:
f[i][j]=f[i-1][k]其中k是非负整数,k是0,9之间的数
边界f[1][i]=1其中i是非负整数,i是0,9之间的数
怎么求f(x)?
为了方便先对x进行10进制拆分,这个操作很经典
1.显然位数比x小的数字都在1,x区间直接统计
2.位数和x一样最高位数字比x小的数字都在1,x区间直接统计
3.位数和x一样最高位和x一样,从左往右扫一遍x各个位,然后判断合法就好了

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<string>
#include<cstring>
using namespace std;
typedef long long ll;
const int SIZE=20;
ll f[SIZE][SIZE]; 
ll a[SIZE]; 
ll n,m;
ll sol(ll x)
{
	int len=0;
	while(x>0ll) a[++len]=x%10,x/=10;
	ll sum=0ll;//0ll相当于0,长整型下的0 
	for(int i=1;i<=len-1;i++)
		for(int j=1;j<=9;j++)//枚举每一位数
			sum+=f[i][j];//计算所有可能的数 
	for(int i=1;i<a[len];i++) sum+=f[len][i];
	
	for(int i=len-1;i>=1;i--)
	{
		for(int j=0;j<=a[i]-1;j++)
			if(abs(j-a[i+1])>=2) sum+=f[i][j];
		if(abs(a[i+1]-a[i])<2) break;//小优化 
	}
	return sum;
}
int main()
{
	cin>>n>>m;
	if(n>m) swap(n,m);
	for(int i=0;i<=9;i++)
		f[1][i]=1ll;//初始化1 
	for(int i=2;i<=10;i++)
	{
		for(int j=0;j<=9;j++)
		{
			for(int k=0;k<=9;k++)
			{
				if(abs(k-j)>=2) f[i][j]+=f[i-1][k];//计算f 
			}
		}
	 } 
	 cout<<sol(m+1)-sol(n)<<endl; 
	 return 0;
}

标签:int,ll,2657,windy,位数,include,SIZE
来源: https://blog.csdn.net/CCCCDEV_CCCC/article/details/119394390

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有