【发布时间】:2014-04-06 14:00:25
【问题描述】:
我有这样一个任务:
如果一个数字可以被 K 整除并且它的数字和位于 [P, Q] 中,我们就称它为“幸运”。计算[A, B]中“幸运”数字的数量。
1 ≤ A, B
1≤P,Q≤99,
1 ≤ K ≤ 10^11。
每次测试的时间 - 5 秒
这是我的代码
#include <iostream>
#include <fstream>
using namespace std;
int sum;
long long k;
int number[10];
int digits[10];
int p;
int q;
long long a;
long long b;
int delta;
bool flag = false;
long long memory[100000][100][10][2];
long long pow (int a, int b)
{
long long res = 1;
for(int i = 0; i < b; i++)
res *= a;
return res;
}
int sumOfDigits(long long number)
{
int sum = 0;
while(number != 0)
{
sum += number % 10;
number /= 10;
}
return sum;
}
long long toLong(int digits[], int n)
{
long long sum = 0;
for(int i = 0; i < n; i++)
{
sum *= 10;
sum += digits[i];
}
return sum;
}
long long function(long long remainder// the remainder of division by k,
int currSum // current sum of digits,
int n //number of digit to be added,
bool allDigitsAllowed //says if all digits can be added to number)
{
if(n == 10)
{
int counter = 0;
for(int i = p; i <= q; i++)
{
long long res = i - currSum + remainder;
if(res%k == 0 && (allDigitsAllowed || i-currSum <= number[9]))
{
counter++;
if(!allDigitsAllowed && number[9] == i-currSum)
flag = true;
}
}
return counter;
}
long long res = 0;
int temp = 0;
while(currSum + temp <= q)
{
long long tempRemainder = (temp*pow(10,10-n)+remainder)%k;
if(temp == number[n-1] && !allDigitsAllowed)
{
if(tempRemainder < 100000)
{
if(memory[tempRemainder][currSum+temp][n+1][false] == -1)
memory[tempRemainder][currSum+temp][n+1][false] = function(tempRemainder, currSum + temp, n+1,false);
res += memory[tempRemainder][currSum+temp][n+1][false];
}
else
res += function(tempRemainder, currSum + temp, n+1,false);
//res += function(tempRemainder, currSum + temp, n+1,false);
break;
}
else
{
if(tempRemainder < 100000)
{
if(memory[tempRemainder][currSum+temp][n+1][true] == -1)
memory[tempRemainder][currSum+temp][n+1][true] = function(tempRemainder, currSum + temp, n+1,true);
res += memory[tempRemainder][currSum+temp][n+1][true];
}
else
res += function(tempRemainder, currSum + temp, n+1,true);
}
temp++;
}
return res;
}
long long F (long long a)
{
flag = false;
memset(&number, 0, sizeof(number));
sum = 0;
int i = 9;
while(a != 0)
{
number[i] = a%10;
a /= 10;
i--;
}
for(int j = 0; j < 10; j++)
swap(number[j],number[9-j]);
return function(0,0,1,false);
}
int main()
{
ifstream in("lucky.in");
ofstream out("lucky.out");
in >> k >> p >> q >> a >> b;
sum = p;
memset(&memory, -1, sizeof(memory));
long long result = - F(a) + flag;
memset(&memory, -1, sizeof(memory));
out<< result + F(b) << endl;
return 0;
}
在这个解决方案中,我尝试用确定的数字总和来制作一个数字,一个接一个地添加数字。 问题是我无法记住除以 k 的所有余数。
那么我该如何处理这个问题呢?
【问题讨论】:
-
由于
F是高计算密集型的,我建议从A循环到B(K由K以正确的起点)而不是计算F(B) - F(A)。 -
很高兴能解释一下您的算法应该如何工作。如果 K 很大和/或 A 和 B 靠得很近,则该算法似乎效率很低。
-
闻起来像作业:)
-
@Jarod42 我已经试过了,但它没有通过 5sec 测试
标签: c++ algorithm dynamic-programming