数位dp

1. windy数。

题意:求给定区间范围内的,求相邻数位之差绝对值不小于2的数的个数。

题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1026

code:

#include<string.h>
#include<stdio.h>
#include<iostream>
using namespace std;
const int maxn = 12;
int f[maxn][10];
int d[maxn];
bool check(int x, int y) {
    return x - y >= 2 || y - x >= 2;
}
void init() {
    memset(f, 0, sizeof(f));
    for(int i = 0; i < 10; i++) f[1][i] = 1;
    for(int i = 2; i < maxn; i++) {
        for(int j = 0; j < 10; j++) {
            for(int k = 0; k < 10; k++) {
                if(j == 0 || check(j, k)) f[i][j] += f[i-1][k];
            }
        }
    }
}
int solve(int x) {
    int m = 0;
    if(x == 0) m = 1;
    memset(d, 0, sizeof(d));
    while(x) {
        d[m++] = x % 10;
        x /= 10;
    }
    int ans = 0;
    for(int i = m - 1; i >= 0; i--) {
        for(int j = 0; j < d[i]; j++) {
            if(i == m - 1 || check(d[i+1], j)) ans += f[i+1][j];
        }
        if(i != m - 1 && !check(d[i], d[i+1])) break;
        if(!i) ans++;
    }
    return ans;
}
int main() {
    int a, b;
    init();
    while(~scanf("%d%d", &a, &b)) {
        printf("%d\n", solve(b) - solve(a-1));
    }
}
2. Investigating Div-Sum Property (UVA 11361)
#include<stdio.h>
#include<string.h>
const int maxn = 10;
const int maxk = 90;
int P[maxn];
int f[maxn][maxk][maxk];
int d[maxn];
int A, B, K;
void init() {
    P[0] = 1;
    for(int i = 1; i < maxn; i++) P[i] = P[i-1] * 10;
}
void calc() {
    memset(f, 0, sizeof(f));
    f[0][0][0] = 1;
    for(int t = 1; t < maxn; t++) {
        for(int a = 0; a < maxk; a++) {
            for(int b = 0; b < maxk; b++) {
                for(int c = 0; c < 10; c++) {
                    int ta = (a + c * P[t-1]) % K;
                    int tb = (b + c) % K;
                    f[t][ta][tb] += f[t-1][a][b];
                }
            }
        }
    }
}
int solve(int x) {
    if(x == 0) return 1;
    memset(d, 0, sizeof(d));
    int m = 0;
    while(x) {
        d[m++] = x % 10;
        x /= 10;
    }
    int ans = 0;
    int pExp, pSum;
    pExp = pSum = 0;
    for(int i = m - 1; i >= 0; i--) {
        for(int j = 0; j < d[i]; j++) {
            int a = (K - (pExp + j * P[i]) % K) % K;
            int b = (K - (pSum + j) % K ) % K;
            ans += f[i][a][b];
        }
        pExp = (pExp + P[i] * d[i]) % K;
        pSum = (pSum + d[i]) % K;
        if(i == 0 && pExp == 0 && pSum == 0) ans++;
    }
    return ans;
}
int main() {
    init();
    int kase;
    scanf("%d", &kase);
    while(kase--) {
        scanf("%d%d%d", &A, &B, &K);
        int ans = 0;
        if(K < maxk) {
            calc();
            ans = solve(B) - solve(A-1);
        }
        printf("%d\n", ans);
    }
    return 0;
}


 
 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值