codeforces 55D. Beautiful numbers 数位dp
2015-12-10 23:51
363 查看
题目链接
一个数, 他的所有位上的数都可以被这个数整除, 求出范围内满足条件的数的个数。
dp[i][j][k], i表示第i位, j表示前几位的lcm是几, k表示这个数mod2520, 2520是1-9之间数的lcm。 然后这样数组就要开成20*2520*2520, 太大了, 所以我们将lcm离散, 因为1-9的lcm根本没有那么多的数, 实际上只有48个。
这题好难想...
一个数, 他的所有位上的数都可以被这个数整除, 求出范围内满足条件的数的个数。
dp[i][j][k], i表示第i位, j表示前几位的lcm是几, k表示这个数mod2520, 2520是1-9之间数的lcm。 然后这样数组就要开成20*2520*2520, 太大了, 所以我们将lcm离散, 因为1-9的lcm根本没有那么多的数, 实际上只有48个。
这题好难想...
#include<bits/stdc++.h> using namespace std; #define mem1(a) memset(a, -1, sizeof(a)) #define ll long long int digit[30], len, idx[3000]; ll dp[30][2522][50]; int gcd(int a, int b) { return b==0?a:gcd(b, a%b); } int get_lcm(int a, int b) { return a/gcd(a, b)*b; } void init() { int num = 0; for(int i = 1; i<=2520; i++) { if(2520%i==0) idx[i] = num++; } mem1(dp); } ll dfs(int len, int lcm, int num, int f) { if(!len) { return num%lcm==0; } if(!f&&dp[len][num][idx[lcm]]!=-1) return dp[len][num][idx[lcm]]; ll ret = 0, maxx = f?digit[len]:9; for(int i = 0; i<=maxx; i++) { if(i == 0) { ret += dfs(len-1, lcm, (num*10)%2520, f&&i==maxx); } else { int tmp = get_lcm(lcm, i); ret += dfs(len-1, tmp, (num*10+i)%2520, f&&i==maxx); } } if(!f) return dp[len][num][idx[lcm]] = ret; return ret; } ll cal(ll n) { len = 0; while(n) { digit[++len] = n%10; n/=10; } return dfs(len, 1, 0, 1); } int main() { ll a, b, t; init(); cin>>t; while(t--) { scanf("%I64d%I64d", &a, &b); printf("%I64d\n", cal(b)-cal(a-1)); } return 0; }
相关文章推荐
- Linux输入命令出错时快速编辑指令
- [Linux]crontab 创建定时任务
- geeksforgeeks Count number of binary strings without consecutive 1’s
- android中textview竖排显示,只能说功能实现了
- UESTC 839
- 爬爬爬之路:UI(十七) 数据持久化(SQLite3数据库实现)
- Android Handler解析
- 链式队列模板
- OC学习篇之---Foundation框架中的NSString对象和NSMutableString对象
- LeetCode 169:Majority Element
- 七牛---使用七牛给网站加速详解
- Javascript 闭包
- Smoke Testing(冒烟测试)
- UESTC 838
- Redux学习笔记
- js-----javascript的编写方式
- iOS开发之静态库.a的制作教程
- Session的生命周期
- cf 605A Sorting Railway Cars 贪心 简单题
- 【cocos2d-x 3D游戏开发】2: 2D基础回顾---理解CCMenu类的实现, 实现点击放大的菜单按钮