Reputation: 6998
i have written a c++ code for generating first and last k digits of a number as large as 10^9. (k<=9).
cin>>n>>k;
cout << (unsigned long)floor(pow(10.0, modf(n*log10((double)n), &dummy) + k - 1)) << " "; // code that prints the first k digits
long long int ans = foo(n,k); // function that prints the last k digits
if(ans==0)
{
for(int i=0;i<k;i++) cout << "0";
}
else{
stringstream ss;
string s;
ss<<ans;
ss>>s;
if(s.size()!=k)
{
for(int i=0;i<(k-s.size());i++)
s="0"+s;
}
cout<<s;
}
where function foo() is:
long long int foo(int n, int k) // code of the function
{
long long int m=1;
for(; k > 0; k--) m*=10;
long long int r=1, t=n % m;
while(n)
{
if (n % 2)
r = r * t % m;
t = t * t % m;
n >>= 1;
}
return r;
}
this gives me output as: if given 9 and 3 as inputs, it gives first and last 3 digits of 9 to the power 9 (9^9) i.e. 387 and 489. But I m still missing out some test cases. Can anyone please help me finding out the test case for which my code wouldn't work ?
1 ≤ n ≤ 109, 1 ≤ k ≤ 9 the problem statement: http://www.codechef.com/problems/MARCHA4/
Upvotes: 5
Views: 2888
Reputation: 283624
I think the problem is using floating point. Finding the first digit of a number actually requires perfect precision.
Unfortunately, the contest judge evidently doesn't understand that "number of significant digits" != "number of correct digits".
Perhaps there is some clever way to exactly compute (n*n, n = 10*9) without exhausting memory, but finding the first digits of a very good estimate is simply not the same as finding the first digits of the answer.
Upvotes: 0
Reputation: 16768
This doesn't really answer the question, and its almost trivially easy, but I figure it might be worth sharing. If there were a "long comment" capability I'd be using it.
EDIT: just noticed using str instead of repr will eliminate the L on its own
def firstAndLastDig(k, num):
s = str(num)
return (s[:k], s[-k:])
def firstAndLastDigSelfExp(k,n):
return firstAndLastDig(k,n**n)
Overflow is not an issue (the only thing is dealing with the L if you use repr instead of str),
firstAndLastDigSelfExp(6,12)
('891610', '448256')
firstAndLastDigSelfExp(42,491)
('209417336844579728122309696211520194012462', '160453713040914743773217804810667483135091')
And neither are leading zeroes
>>> firstAndLastDigSelfExp(4,9)
('3874', '0489')
This isn't do say the modular logs and stuff aren't cool - on the contrary I really liked reading about how you did this without generating the entire number. I didn't know about modf at all until reading OP's question and the body of foo is very interesting.
Upvotes: 1
Reputation: 283624
Are you told that n
is a positive integer? For example, (-8)^(-8)
is perfectly well expressible in decimal but your program can't handle it.
Upvotes: -1
Reputation: 283624
Assume that k = 9
. Now, m = 1e9
, and t <= 1e9 - 1
.
t * t
then may be as high as 1e18 - 2e9 + 1
, which needs ... 59.8 bits.
Ok, not a problem with a 64-bit long long int
, which has 63 bits of magnitude (and 1 of sign), but I'll leave this here so others don't repeat the same analysis.
Upvotes: -1
Reputation: 43477
If n^n <= 10^9
, in which case your code seems to work fine. However, if you allow bigger n
, say 11^11
, and ask for the last 4 digits of that, which are 0611
, your code will only print 611
. Basically, it doesn't print any leading zeroes when it should.
Upvotes: 2