wenbao与数位dp

 套路题,在数字上面进行dfs,要点是剪枝(记忆的状态不同,效果大不一样)

 

 ---------------------------------------------------

 

http://acm.hdu.edu.cn/showproblem.php?pid=2089

 

 1 #include <iostream>
 2 #include <string.h>
 3 using namespace std;
 4 int n, m, num[20], dp[20][2];
 5 int d(int pos, int pre, int st, bool limi){
 6     if(pos == -1) return 1;
 7     if(!limi && dp[pos][st] != -1) return dp[pos][st];
 8     int up = limi ? num[pos] : 9;
 9     int sum = 0;
10     for(int i = 0; i <= up; ++i){
11         if(pre == 6 && i == 2) continue;
12         if(i == 4) continue;
13         sum += d(pos-1, i, i == 6, limi && i == up);
14     }
15     if(!limi) dp[pos][st] = sum;
16     return sum;
17 }
18 int f(int x){
19     int pos = 0;
20     while(x){
21         num[pos++] = x%10;
22         x /= 10;
23     }
24     num[pos] = 0;
25     return d(pos-1, 1, 0, true);
26 }
27 int main(){
28     memset(dp, -1, sizeof(dp));
29     while(~scanf("%d%d", &n, &m)){
30         if(n == 0 && m == 0) break;
31         printf("%d\n", f(m) - f(n-1));
32     }
33     return 0;
34 }

 

 

 

---------------------------------------------------

 

http://acm.hdu.edu.cn/showproblem.php?pid=6156

 

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <iostream>
 4 using namespace std;
 5 typedef long long ll;
 6 ll dp[40][40][40][2], L, R;
 7 int num[40],temp[40], l, r;
 8 ll dfs(int bas, int start,int cur,bool state,bool fp){
 9     if(cur<0)
10         return state;
11     if(!fp&&dp[bas][start][cur][state]!=-1)
12         return dp[bas][start][cur][state];
13     int fpmax = fp ? num[cur] : (bas-1);
14     ll ret = 0;
15     for(int i = 0; i <= fpmax; i++){
16         temp[cur] = i;
17         if(start == cur && i == 0)
18             ret += dfs(bas, start-1, cur-1, state, fp && i==fpmax);
19         else if(state && cur < (start+1)/2)
20             ret += dfs(bas, start, cur-1, temp[start-cur]==i, fp&&i==fpmax);
21         else
22             ret+=dfs(bas, start, cur-1, state, fp&&i==fpmax);
23     }
24     if(!fp) 
25         dp[bas][start][cur][state] = ret;
26     return ret;
27 }
28 ll f(ll n){
29     ll sum = 0, nn = n;
30     for(int i = l; i <= r; ++i){
31         int len=0;
32         sum += nn;
33         n = nn;
34         while(n){
35             num[len++] = n%i;
36             n /= i;
37         }
38         num[len]=0;
39         sum += dfs(i, len-1, len-1, 1, 1)*(i-1);
40     }
41     return sum;
42 }
43 int main(){
44     int T;
45     scanf("%d", &T);
46     int res = 1;
47     memset(dp,-1,sizeof(dp));
48     while(T--){
49         scanf("%lld%lld%d%d", &L, &R, &l, &r);
50         printf("Case #%d: %lld\n", res++, f(R)-f(L-1));
51     }
52     return 0;
53 }

 

 

-------------------------------------------------

 

http://codeforces.com/problemset/problem/855/E

 

 1 #include <iostream>
 2 #include <string.h>
 3 using namespace std;
 4 #define ll long long
 5 ll n, m, num[66], dp[66][66][1025];
 6 ll d(ll cnt, ll sum, ll pos, ll st, bool pre, bool limi) {
 7     if(pos == -1) return sum == 0;
 8     if(!pre && !limi && dp[cnt][pos][sum] != -1) return dp[cnt][pos][sum];
 9     ll up = limi ? num[pos] : cnt - 1;
10     ll summ = 0;
11     for(ll i = 0; i <= up; ++i) {
12         ll M;
13         if(pre && i == 0) M = sum;
14         else M = sum ^ (1LL << i);
15         summ += d(cnt, M, pos - 1, i, pre && i == 0, limi && i == up);
16     }
17     if(!pre && !limi) dp[cnt][pos][sum] = summ;
18     return summ;
19 }
20 ll f(ll cnt, ll x) {
21     ll pos = 0;
22     while(x) {
23         num[pos++] = x % cnt;
24         x /= cnt;
25     }
26     num[pos] = 0;
27     return d(cnt, 0, pos - 1, 0, true, true);
28 }
29 int main() {
30     memset(dp, -1, sizeof(dp));
31     ll t, x;
32     ll l, r;
33     scanf("%lld", &t);
34     while(t--) {
35         scanf("%lld%lld%lld", &x, &l, &r);
36         printf("%lld\n", f(x, r) - f(x, l - 1));
37     }
38     return 0;
39 }

 

 

--------------------------------------------------

-----------------------------------------------------

-------------------------------------------------------

 

 

 

 

 

只有不断学习才能进步!

 

转载于:https://www.cnblogs.com/wenbao/p/7693498.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值