您的位置:首页 > 其它

《算法竞赛-训练指南》第二章-2.5_UVa 11361

2013-08-11 16:43 309 查看
这道题目写了两天呀,好气愤呀。就是静不下心来,也不知道怎么回事。

也是这题目一直不让我过,改来改去都改不对。所以今天就什么都不想了,重写一边,开始也过不了,不过改了一下就过了。

气愤呀!

这道题目是个好题目,题目的大概意思是这样的:给你a,b,和k,问你在a-b之间有多少个这样的数字x,使得x%k == 0 并且 x的各个数字相加起来的和%k == 0。明显暴力是过不了的。这种题目第一步都是令f(x)表示0-x满足这些条件的数目,则题目就等于f(b) - f(a - 1)。

然后思考,这样的题目其实就类似关于数位的问题了。和数位dp就差不多是一个意思了,都是分解成一部分一部分的,然后再求解,分治的思想,把问题减小化,就能简化问题。

贴出成功的代码吧:(状态不佳呀~!)

#include <stdio.h>
#include <string.h>
#include <iostream>
#include <string>

using namespace std;

int a, b, MOD;

int pow10[11];

int m[11][91][91];

int mod(int n)
{
return (n % MOD + MOD) % MOD;
}

int f(int d, int m1, int m2)
{
if (d == 0)
{
return m1 == 0 && m2 == 0 ? 1 : 0;
}
int &ans = m[d][m1][m2];
if (ans >= 0)
{
return ans;
}
ans = 0;
for (int digit = 0; digit <= 9; digit++)
{
// cout << "d - 1 = " << d - 1 << endl;
// cout << "m1 - digit = " << m1 - digit << endl;
// cout << "m2 - digit * pow10[d - 1] = " << m2 - digit * pow10[d - 1] << endl;
ans += f(d - 1, mod(m1 - digit), mod(m2 - digit * pow10[d - 1]));
}
return ans;
}

int getSum(int x)
{
char digits[11];
sprintf(digits, "%d", x);
int ans = 0;
int sumd = 0;
int sums = 0;
int len = strlen(digits);
for (int i = 0; i < len; i++)
{
int R = len - i - 1;
int cnt = digits[i] - '0';
for (int digit = 0; digit < cnt; digit++)
{
// cout << "R = " << R << endl;
// cout << "mod(-sumd - digit) = " << mod(-sumd - digit) << endl;
// cout << "mod(-sums - digit * pow10[R]) = " << mod(-sums - digit * pow10[R]) << endl;
ans += f(R, mod(-sumd - digit), mod(-sums - digit * pow10[R]));
}
sumd += digits[i] - '0';
sums += (digits[i] - '0') * pow10[R];
}
return ans;
}

void init()
{
pow10[0] = 1;
for (int i = 1; i <= 9; i++)
{
pow10[i] = pow10[i - 1] * 10;
}
}

int main()
{
int T;
init();
scanf("%d", &T);
while (T--)
{
memset(m, -1, sizeof(m));
scanf("%d%d%d", &a, &b, &MOD);
if (MOD > 85)
{
printf("0\n");
}
else
{
// cout << "getSum(b + 1) = " << getSum(b + 1) << endl;
int ans = getSum(b + 1) - getSum(a);
printf("%d\n", ans);
}
}
// system("pause");
return 0;
}


 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: