首页 > 其他分享 >1083. Windy数

1083. Windy数

时间:2022-12-07 20:59:16浏览次数:81  
标签:10 1083 int 样例 整数 Windy define

题目链接

1083. Windy数

Windy 定义了一种 Windy 数:不含前导零且相邻两个数字之差至少为 \(2\) 的正整数被称为 Windy 数。

Windy 想知道,在 \(A\) 和 \(B\) 之间,包括 \(A\) 和 \(B\),总共有多少个 Windy 数?

输入格式

共一行,包含两个整数 \(A\) 和 \(B\)。

输出格式

输出一个整数,表示答案。

数据范围

\(1 \le A \le B \le 2 \times 10^9\)

输入样例1:

1 10

输出样例1:

9

输入样例2:

25 50

输出样例2:

20

解题思路

数位dp

  • 状态表示:\(f[i][j]\) 表示 \(i\) 位,且最后一位为 \(j\),且相邻两个数之间差至少为 \(1\) 的整数个数

  • 状态计算:\(f[i][j]+=f[i-1][k]\),其中 \(|j-k| \geq 2\)

则可以利用 \(f[i][j]\) 求出前 \(i\) 位满足条件的整数个数 \(s[i]\),本题等价于求解前缀和 \(1\sim x\) 内满足条件的整数个数,求出 \(x\) 的位数 \(n\),则对于 \(1\sim n-1\) 的位数贡献为 \(s[n-1]\),现在只用讨论位数为 \(n\) 且不大于 \(x\) 的整数个数,类似于 1081. 度的数量,每一位每一位讨论,对于第一位需要特判,因为第一位不能为 \(0\),而且第一位没有前面数的限制,对于小于当前位 \(A[i]\) 的数 \(j\),同时利用 \(f[i][j]\) 数组,\(f[i][j]\) 表示的以 \(j\) 结尾的 \(i\) 位的方案数,则可以将该整数翻转,即以 \(j\) 首位的 \(i\) 位的整数的方案数,即第一位如果是 \(j\) 的贡献为 \(f[n][j]\),对于其他位,判断是否相邻差至少为 \(2\),如果满足条件,则枚举的 \(j\) 的贡献为 \(f[n-i+1][j]\),另外如果该数本身就满足条件,则还需要加上该数的贡献

  • 时间复杂度:\(O(10\times logw)\)

代码

// Problem: Windy数
// Contest: AcWing
// URL: https://www.acwing.com/problem/content/description/1085/
// Memory Limit: 64 MB
// Time Limit: 1000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

// %%%Skyqwq
#include <bits/stdc++.h>
 
// #define int long long
#define help {cin.tie(NULL); cout.tie(NULL);}
#define pb push_back
#define fi first
#define se second
#define mkp make_pair
using namespace std;
 
typedef long long LL;
typedef pair<int, int> PII;
typedef pair<LL, LL> PLL;
 
template <typename T> bool chkMax(T &x, T y) { return (y > x) ? x = y, 1 : 0; }
template <typename T> bool chkMin(T &x, T y) { return (y < x) ? x = y, 1 : 0; }
 
template <typename T> void inline read(T &x) {
    int f = 1; x = 0; char s = getchar();
    while (s < '0' || s > '9') { if (s == '-') f = -1; s = getchar(); }
    while (s <= '9' && s >= '0') x = x * 10 + (s ^ 48), s = getchar();
    x *= f;
}

int a,b;
int f[15][10],s[15],A[15],n;
void init()
{
	for(int i=0;i<=9;i++)f[1][i]=1;
	for(int i=2;i<=10;i++)
		for(int j=0;j<=9;j++)
			for(int k=0;k<=9;k++)
				if(abs(j-k)>=2)f[i][j]+=f[i-1][k];
	for(int i=1;i<=10;i++)
		for(int j=1;j<=9;j++)s[i]+=f[i][j];
	for(int i=1;i<=10;i++)s[i]+=s[i-1];
}
int get(int x)
{
	if(x==0)return 0;
	n=0;
	do
	{
		A[++n]=x%10;
		x/=10;
	}while(x);
	reverse(A+1,A+1+n);
	int res=s[n-1];
	for(int i=1;i<=n;i++)
	{
		for(int j=0;j<A[i];j++)
		{
			if(i==1)
			{
				if(j)
					res+=f[n][j];
			}
			else
			{
				if(abs(j-A[i-1])>=2)res+=f[n-i+1][j];
			}
		}
		if(i>1&&abs(A[i]-A[i-1])<2)break;
		if(i==n)res++;
	}
	return res;
}
int main()
{
    init();
    scanf("%d%d",&a,&b);
    printf("%d",get(b)-get(a-1));
    return 0;
}

标签:10,1083,int,样例,整数,Windy,define
From: https://www.cnblogs.com/zyyun/p/16964494.html

相关文章

  • CF1083C Max Mex
    题意给定一棵树,点权为\(0\simn-1\)的排列。每次交换两个点的点权或者询问整棵树上所有路径中,路径上点权的\(\operatorname{mex}\)最大值。Solution比较神奇的转化......
  • P1083 [NOIP2012 提高组] 借教室
    #include<iostream>usingnamespacestd;constintN=1e6+1;intn,m;inta[N];structnode{inttag,sum;node(){tag=sum=0;}v......
  • 4.错误代码C1083
    有的时候在VS中遇到的errorC1083:无法打开**:“*.*”:Nosuchfileordirectory的错误,这里总结了我遇到过的情况:错误 C1083 无法打开包括文件:“MyArray.h”:No......
  • 【Visual Studio 2022】 首次安装出现 fatal error C1083: 无法打开包括文件:“crtdbg
    VS2022包括的版本如下:Windows版本WindowsSDK版本Windows10版本1903Windows10SDK版本1903(10.0.18362.1)Windows10版本2004Windows10SDK版本2004(10......
  • Windy数
    数位DP原题链接题目描述:计算从[l,r]中windy数的个数windy数:不含前导零且任意相邻两位数字之差至少为2由于不含前导零,所以最高位不能从0开始,只能从1~x-1考虑状态表......
  • CF1083C Max Mex
    传送门思路对线段树的功能理解又加深了假设我们枚举答案为\(x\),那么要满足有一条链包含了\(1\)~\(x-1\)的数我们考虑建立一棵线段树,下标为点权,区间记录的是\([l......