BZOJ 1026 Scoi2009 windy数

1026: [SCOI2009]windy数

Time Limit: 1 Sec  Memory Limit: 162 MB
Submit: 8765  Solved: 3957
[Submit][Status][Discuss]

Description

  windy定义了一种windy数。不含前导零且相邻两个数字之差至少为2的正整数被称为windy数。 windy想知道,
在A和B之间,包括A和B,总共有多少个windy数?

Input

  包含两个整数,A B。

Output

  一个整数

Sample Input

【输入样例一】
1 10
【输入样例二】
25 50

Sample Output

【输出样例一】
9
【输出样例二】
20

HINT

【数据规模和约定】

100%的数据,满足 1 <= A <= B <= 2000000000 。

Source

我觉得网上大部分的题解写的有点扯

只用到了一小部分dp,其他的都是模拟

首先dp预处理出来f[i][j]表示以最高位为j的i位数总共含有多少个windy数

我们求n~m的windy数,也就是求1~m的windy数-1~n的windy数

感觉没有实际的例子不是很好说代码是怎么运行的,举个例子吧

比如说2596476

首先1~1999999之间的所有windy数都是符合条件的

2000000~2499999之间的windy数也都是符合条件的

2500000~2589999之间的windy也都是符合条件的

同理 

2590000~2595999     2596000~2596399

2596400~2596479     2596470~2596479

这些区间中的windy数都是符合条件的

我们依次去枚举这些区间,把答案累加到sum上

具体数先看代码,最后把1~n中的windy数和1~m中的windy数相减即为答案

#include <bits/stdc++.h>
#define ll long long
using namespace std;
inline int read(){
    int x=0;int f=1;char ch=getchar();
    while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
    while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
int f[20][15]={};
string str1,str2;
void init(){
   cin>>str1;cin>>str2;
}
void solve(){
    for(int i=0;i<=9;i++){
        f[1][i]=1;
    }
    for(int i=2;i<=15;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];
            }
        }
    }
    int str1l=str1.size();int str2l=str2.size();
    int sum1=0;int sum2=0;
    for(int i=1;i<str1l;i++){
        for(int j=1;j<=9;j++){
            sum1+=f[i][j];
        }
    }
    for(int i=1;i<str2l;i++){
        for(int j=1;j<=9;j++){
            sum2+=f[i][j];
        }
    }
    for(int i=1;i<str1[0]-'0';i++){
        sum1+=f[str1l][i];
    }
    for(int i=1;i<str2[0]-'0';i++){
        sum2+=f[str2l][i];
    }
    for(int i=0;i<str1l-1;i++){
        int tn=str1[i]-'0';
        int tnt=str1[i+1]-'0';
        for(int j=0;j<tnt;j++){
            if(abs(tn-j)>=2) sum1+=f[str1l-i-1][j];
        }
        if(abs(str1[i+1]-str1[i])<2) break;
    }
    for(int i=0;i<str2l;i++){
        int tn=str2[i]-'0';
        int tnt=str2[i+1]-'0';
        for(int j=0;j<tnt;j++){
            if(abs(tn-j)>=2) sum2+=f[str2l-i-1][j];
        }
        if(abs(str2[i+1]-str2[i])<2) break;
        if(i==str2l-2) sum2++;
    }
    cout<<sum2-sum1<<endl;
}
int main(){
    //freopen("All.in","r",stdin);
    //freopen("zhang.out","w",stdout);
    init();
    solve();
    return 0;
}

对拍代码

#include <bits/stdc++.h>
#define ll long long
using namespace std;
inline int read(){
    int x=0;int f=1;char ch=getchar();
    while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
    while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
int main(){
    freopen("All.in","w",stdout);
    srand(int(time(NULL)));
    int n=rand()%100007+1;int m=rand()%100007+1;
    if(n>m) swap(n,m);
    cout<<n<<' '<<m<<endl;
    return 0;
}

  

 

posted @ 2017-11-23 17:51  zhangenming  阅读(...)  评论(... 编辑 收藏