zoukankan      html  css  js  c++  java
  • 1587: 【例 3】Windy 数

    1587: 【例 3】Windy 数

    时间限制: 1000 ms 内存限制: 524288 KB
    提交数: 596 通过数: 366
    【题目描述】

    原题来自:SCOI 2009

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

    Windy 想知道,在 A 和 B 之间,包括 A 和 B,总共有多少个 Windy 数?
    【输入】

    一行两个数,分别为A,B。
    【输出】

    输出一个整数,表示答案。
    【输入样例】

    1 10

    【输出样例】

    9

    【提示】

    样例输入 2

    25 50

    样例输出 2

    20

    数据范围与提示:

    20% 的数据,满足 1≤A≤B≤106 ;

    100% 的数据,满足 1≤A≤B≤2×109 。

    思路:
    发现自己什么都不会qwq
    这只是一个很基础的板子qwq
    啊啊啊ε=ε=ε=(#>д<)ノ

    f[i][j]表示处理到第i位,第i位上的数字是j,首先在我们dfs之前要进行预处理,在预处理的时候就判断是否符合windy数定义
    接下来对于所有小于x的数进行处理,因为我们的f[i][j]定义的是所有不超过上界的数,所以对于每一位都不超过x所对应的每一位的上界的数直接加上f[i][j]就可以
    但是对于这样的数:有某一位达到了上界,我们就不能通过f[i][j]数组来转移,这时候应当对这样的数特殊处理,处理方式是枚举上界,枚举当前所在位上的数,如果符合windy数定义,那么就加上f[i][j](因为这个时候的确符合f[i][j]未达到上界),ans+=f[i][j]

    代码:

    #include<bits/stdc++.h>
    #define ll long long 
    #define maxn 15
    using namespace std;
    
    ll a,b;
    ll f[maxn][maxn];
    ll p[maxn];
    
    void prepare()
    {
    //	f[0][0]=0;
    	p[0]=1;
    	for(int i=1;i<=13;i++) p[i]=p[i-1]*10;
    	for(int i=0;i<=9;i++) f[1][i]=1;
    	for(int i=2;i<=13;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]/*,cout<<f[i][j]<<" "*/;
    			}
    }
    
    ll work(ll x)
    {
    	ll ans=0;
    	
    //	if(x==1) return 0;
    	ll w=0;
    	ll y;
    	while(p[w]<=x) w++;//找到比x小的位数,只要位数比x小,那么一定是答案之一
    //	cout<<w<<" ";
    	for(int i=1;i<w;i++)
    		for(int j=1;j<=9;j++)//从1开始是为了排除前导0 
    		{
    			ans+=f[i][j];
    //			cout<<f[i][j]<<" ";
    //			cout<<ans<<'
    '; 
    		 } 
    		 
    	y=x/p[w-1];//找到位数与x相同的位数上的数
    	ll pre=y;
    //	cout<<ans<<" ans1
    ";
    	for(int i=1;i<y;i++) ans+=f[w][i]/*,cout<<ans<<'
    '*/;//这个数也比x小,从1开始是为了排除前导0
    //	cout<<ans<<" ans2
    ";
    	x%=p[w-1]; 
    	for(int i=w-1;i>=1;i--)
    	{
    		y=x/p[i-1];
    		for(int j=0;j<y;j++)
    			if(abs(j-pre)>=2) ans+=f[i][j]/*,cout<<ans<<'
    ';*/;
    			if(abs(pre-y)<2) break;
    			pre=y;
    			x%=p[i-1];
    	}
    //	cout<<ans<<" @@@@
    ";
    	return ans;
    		 
    	
    	
    }
    
    int main()
    {
    	cin>>a>>b;
    	prepare();
    //	prepare();
    //cout<<b+1<<" uuhuo  "<<work(b+1)<<'
    ';
    //cout<<a<<" kukhkuh "<<work(a)<<'
    ';
    	printf("%lld
    ",work(b+1)-work(a));
    	return 0;
    }
    
    #include<bits/stdc++.h>
    #define ll long long
    #define maxn 15
    using namespace std;
    
    ll f[maxn][maxn],a,b,c[maxn];
    
    ll dfs(ll l,ll last,bool lim,bool zero)
    {
    	if(!l) return 1;
    	if(!lim&&!zero&&f[l][last]!=-1) return f[l][last];
    	
    	ll limist=lim?c[l]:9;
    	ll tmp=0,p;
    	for(int i=0;i<=limist;i++)
    	{
    		if(abs(i-last)<2) continue;
    		p=i;
    		if(zero&&p==0) p=-2;
    		tmp+=dfs(l-1,p,lim&&(i==limist),p==-2);
    	}
    	if(!zero&&!lim) f[l][last]=tmp;
    	return tmp;
    }
    
    ll work(ll x)
    {
    	memset(f,-1,sizeof(f));
    	memset(c,0,sizeof(c));
    	ll cnt=0;
    	while(x)
    	{
    		c[++cnt]=x%10;
    		x/=10;
    	}
    	
    	return dfs(cnt,-2,1,1);
    	
    }
    
    int main()
    {
    	cin>>a>>b;
    	cout<<work(b)-work(a-1)<<'
    ';
    	return 0;
    }
    
  • 相关阅读:
    278.First Bad Version
    277. Find the Celebrity
    256.Paint House
    276. Paint Fence
    275. H-Index II
    274. H-Index
    273. Integer to English Words
    272. Closest Binary Search Tree Value II
    270. Closest Binary Search Tree Value
    271. Encode and Decode Strings
  • 原文地址:https://www.cnblogs.com/yxr001002/p/14437982.html
Copyright © 2011-2022 走看看