Sub-string divisibility
The number, 1406357289, is a 0 to 9 pandigital number because it is made up of each of the digits 0 to 9 in some order, but it also has a rather interesting sub-string divisibility property.
Let d1 be the 1st digit, d2 be the 2nd digit, and so on. In this way, we note the following:
- =406 is divisible by 2
- =063 is divisible by 3
- =635 is divisible by 5
- =357 is divisible by 7
- =572 is divisible by 11
- =728 is divisible by 13
- =289 is divisible by 17
Find the sum of all 0 to 9 pandigital numbers with this property.
1406357289是一个0至9全数字数,因为它由0到9这十个数字排列而成;但除此之外,它还有一个有趣的性质:子串的可整除性。
记d1是它的第1个数字,d2是第2个数字,依此类推,注意到:
- =406能被2整除
- =063能被3整除
- =635能被5整除
- =357能被7整除
- =572能被11整除
- =728能被13整除
- =289能被17整除
找出所有满足同样性质的0至9全数字数,并求它们的和。
这个题目要求,满足0-9全数组的数,并且每3位会满足题目条件的数的和,那么进行分析;
1.如何求0-9全数字
2.求到全数字怎么去进行,对没3位的题目条件进行判断;
进行对第一点分析,找10个位置,第一个位置放了一个数,那么这个数就在后面不能用了,所以需要记录这个位置放了的数,后面依次进行这样的操作;到最后一个位置填完最后一个数时,进行回溯,回溯到第二位置,进行填之前没有填过的数,一直回溯加递归加循环的一个过程,就可以求到,0-9全数字的全排列;
对第二点分析,可以在第一点求得的情况下,讲数字进行每位存储在数组中,那么就可以很好的找到每位的数组进行来判断了;
下面是代码实现的过程:
#include <stdio.h> #include <math.h> #include <string.h> #define MAX_N 5000000 int num[10] = {0};//用来记录每位数字是否被用过 char buff[15] = {0};//用来排列 int sum[MAX_N + 5][15];//用来存满足题目含0-9数字的10位数的数值, int s = 0; void get_int(char *buff) {//讲字符串换位数组中 sum[0][0]++; for (int i = 0; buff[i]; i++) { sum[sum[0][0]][i] = buff[i] - '0'; } return ; } void get_num(int n, int k, char *buff) {//获取0-9的全排列 if (k == 10) {//当k==10说明以及有10位了,所以进行转换 if (buff[0] == '0') return ;//第一位为0不满住题目条件所以不记录 get_int(buff); return ; } for (int i = n; i < 10; i++) { while (num[s]) {//来确定当前数是否被用过 s++; if (s == 10) s = 0; } buff[k] = s + '0';//将这个数赋进字符串 num[s] = 1;//现在标记这个数被用 get_num(n + 1, k + 1, buff);//开始对下个位置进行赋值 num[buff[k] - '0'] = 0;//回溯当前位置的数字未被用过,因为s一直都在变化,所以这里不能用s进行回溯只能用当前位置的数字来进行回溯 } return ; } long long is_interesting_num(int *a) { int fact[7] = {2, 3, 5, 7, 11, 13, 17}, j = 0;//题目条件的被除数 int g = a[0];//第一位直接赋值,只要不为0就可以,在上面的函数中已经剔除掉第一位为0的情况 long long return_num = a[0];//如果满足条件,进行返回的值 for (int i = 1; i < 10; i++) { g = g * 10 + a[i]; return_num = return_num * 10 + a[i]; if (i < 3) continue;//当i<3时,还不足3位 g -= a[i - 3] * 1000;//假如当前是第4位,就需要减去第一位来进行判断下面一步操作 if (g % fact[j++]) return 0; } return return_num; } void output(int *a) { for (int i = 0; i < 10; i++) { printf("%d", a[i]); } putchar(10); return ; } int main() { get_num(0, 0, buff); long long ans = 0; for (int i = 1; i <= sum[0][0]; i++) { long long g = is_interesting_num(sum[i]); if (!g) continue; ans += g; } printf("%lld\n", ans); return 0; }
最终答案: 16695334890