51nod 1232:完美数

来源:互联网 发布:淘宝详情页怎么加链接 编辑:程序博客网 时间:2024/06/05 11:48

1232 完美数
题目来源: 胡仁东
基准时间限制:2 秒 空间限制:131072 KB 分值: 160 难度:6级算法题
 收藏
 关注
如果一个数能够被组成它的各个非0数字整除,则称它是完美数。例如:1-9都是完美数,10,11,12,101都是完美数,但是13就不是完美数(因为13不能被数字3整除)。
现在给定正整数x,y,求x和y之间(包含x和y的闭区间)共有多少完美数。

题目作者为:hrdv
Input
第1行:一个数T,表示后面用作输入测试的数的数量。(1 <= T <= 10000)第2 - T + 1行:每行2个数,X, Y中间用空格分割。(1 <= X <= Y <= 10^18)
Output
输出共T行,对应区间中完美数的数量。
Input示例
21 912 15
Output示例
92

一个数整除所有位置上的数,也就是整除这些数的lcm,最多2520。然后记录每一个数对2520的余数,数位dp。另外,lcm的数量不是很多,离散化记录。

代码:

//#pragma comment(linker, "/STACK:655360000")  #pragma warning(disable:4996)#include <iostream>#include <functional>#include <algorithm>#include <cstring>#include <vector>#include <string>#include <cstdio>#include <cmath>#include <queue>#include <stack>#include <deque>#include <set>#include <map>using namespace std;typedef long long ll;#define INF 0x333f3f3f#define repp(i, n, m) for (int i = n; i <= m; i++)#define rep(i, n, m) for (int i = n; i < m; i++)#define sa(n) scanf("%d", &(n))const ll mod = 2520;const int maxn = 1e5 + 5;const double PI = acos(-1.0);int dig[20], ha[2550];ll dp[20][50][2550];ll gcd(ll x, ll y){if (y == 0)return x;else{return gcd(y, x%y);}}void init(){int i, j, k, cnt;memset(dp, -1, sizeof(dp));cnt = 0;for (i = 1; i <= 2520; i++){if (mod%i == 0){cnt++;ha[i] = cnt;}}}ll dfs(ll n, ll top, ll lcm, ll mo){if (n <= 0)return mo%lcm == 0;if (!top&&dp[n][ha[lcm]][mo] != -1)return dp[n][ha[lcm]][mo];int end = (top == 1) ? dig[n] : 9;int i, j, k;ll ans = 0;for (i = 0; i <= end; i++){int m = (mo * 10 + i) % mod;int lcm_tmp;if (i != 0)lcm_tmp = lcm / gcd(lcm, i)*i;elselcm_tmp = lcm;ans += dfs(n - 1, top&(i == end), lcm_tmp, m);}if(!top)dp[n][ha[lcm]][mo] = ans;return ans;}ll solve(ll x){int i, j, k, cnt = 0;memset(dig, 0, sizeof(dig));while (x){cnt++;dig[cnt] = x % 10;x /= 10;}ll r = dfs(cnt, 1, 1, 0);return r;}int main() {init();int t;sa(t);while (t--){ll x, y;scanf("%lld%lld", &x, &y);printf("%lld\n", solve(y) - solve(x - 1));}return 0;}

0 0
原创粉丝点击