Unexpected output of c++ program - c++

I was solving http://codeforces.com/problemset/problem/552/B.
In my first attempt I came up with something like:
#include <bits/stdc++.h>
using namespace std;
int digit(long a){
int i=0;
while(a){
a/=10;
i++;
}
return i;
}
int main()
{
long n;
long long s=0;
ios_base::sync_with_stdio(false);
cin.tie(NULL);
cin>>n;
int dig=digit(n),i=0;
while(i<dig){
s+=(n-pow(10,i)+1);
i++;
}
cout<<s;
return 0;
}
But for input
1000000
My program outputed
5888895
I was expecting
5888896
In my second try I wrote pow function for myself:
#include <bits/stdc++.h>
using namespace std;
int digit(long a){
int i=0;
while(a){
a/=10;
i++;
}
return i;
}
long long pow1(int a){
long long s=1;
while(a--){
s*=10;
}
return s;
}
int main()
{
long n;
long long s=0;
ios_base::sync_with_stdio(false);
cin.tie(NULL);
cin>>n;
int dig=digit(n),i=0;
while(i<dig){
long long aux=pow1(i);
s+=(n-aux+1);
i++;
}
cout<<s;
return 0;
}
And this time it was correct.How can one explain the working behind it?

The problem with the built-in pow function is that is does not work as accurate as your function. pow calculates x to the y as exp(y*log(x)). This generic formula works with all (even non-integral) exponents, and its performance is (mostly) independent on the arguments. The problem with that formula is, that pow(10,2) might be 99.9, which gets truncated to 99 when it is converted to an integer type. Try pow(10,i) + 0.5 to perform proper rounding.

You may not need pow here. This works as expected and is faster too.
#include <iostream>
typedef unsigned long long ull;
using namespace std;
ull count(ull n) {
ull i = 0;
for (; n; ++i) n /= 10;
return i;
}
int main() {
ull n;
cin >> n;
ull digits = count(n);
ull ans = digits * (n + 1);
for (ull i = 0, j = 1; i < digits; ++i, j *= 10)
ans -= j;
cout << ans;
return 0;
}
All testcases passed on codeforces.com

You just need to multiply pow(10,i-1) with 0.1. That will do the work you needed.
#include <iostream>
#include <cmath>
using namespace std;
int digit_calc(long long num);
long long digit_counter(long long num, int digit);
int main()
{
long long num,digit,total;
cin>>num;
digit=digit_calc(num);
total=digit_counter(num, digit);
cout<<total<<endl;
return 0;
}
int digit_calc(long long num){
int digit=0;
while(num){
digit++;
num=num/10;
}
return digit;
}
long long digit_counter(long long num, int digit){
long long sup,net,total=0;
while(num){
sup=0.1*(pow(10,digit)-1);
net=num-sup;
total=total+(net*digit);
num=sup;
digit--;
}
return total;
}
It passed all test cases on codeforce.

Related

Why is recursive solution faster than an iterative solution for this case?

I am trying to obtain a solution for this question https://www.spoj.com/problems/COINS/.
But oddly enough, my iterative solution:
#include <iostream>
using namespace std;
int main() {
int n;
while(cin >> n){
long long int dp[n+2];
dp[0]=0;
for(long long int i=1; i<=n; i++)
dp[i]=max(dp[i/2]+dp[i/3]+dp[i/4], i);
cout << dp[n] <<endl;
}
return 0;
}
gets a TLE, while the recursive solution for this(Not mine) gets accepted in no time:
#include <cstdio>
#include <map>
#include <algorithm>
using namespace std;
map<int, long long> dp;
long long f(int n){
if(n==0) return 0;
if(dp[n]!=0) return dp[n];
long long aux=f(n/2)+f(n/3)+f(n/4);
if(aux>n) dp[n]=aux;
else dp[n]=n;
return dp[n];
}
int main(){
int n;
while(scanf("%d",&n)==1) printf("%lld\n",f(n));
return 0;
}
Shouldn't it be the opposite? I am genuinely confused.
The iterative solution is linear in n i.e it's O(n) while the recursive one is O(log_2 n ) from what I can understand.

Declaring 2-dimensional array in "Edit distance" on spoj locally gives runtime error?

While solving http://www.spoj.com/problems/EDIST/ , when I declare the 2-d array globally: (http://ideone.com/jG3jPW)
#include <iostream>
using namespace std;
long long int s[2001][2001];
int main() {
int t;
string a,b;
long long int i,j;
for(i=0;i<2001;i++)
{
s[i][0]=i;
s[0][i]=i;
}
cin>>t;
while(t>0)
{
cin>>a>>b;
t--;
for(i=1;i<=a.length();i++)
{
for(j=1;j<=b.length();j++)
{
if(a[i-1] == b[j-1])
s[i][j]=s[i-1][j-1];
else
s[i][j] = min(min(s[i-1][j],s[i-1][j-1]),s[i][j-1]) + 1;
}
}
cout<<s[i-1][j-1]<<"\n";
}
return 0;
}
no error occurs. But when i declare the same array locally(http://ideone.com/Tyj6UU),
#include <iostream>
using namespace std;
int main() {
int t;
string a,b;
long long int i,j;
long long int s[2001][2001]; //declared locally
for(i=0;i<2001;i++)
{
s[i][0]=i;
s[0][i]=i;
}
cin>>t;
while(t>0)
{
cin>>a>>b;
t--;
for(i=1;i<=a.length();i++)
{
for(j=1;j<=b.length();j++)
{
if(a[i-1] == b[j-1])
s[i][j]=s[i-1][j-1];
else
s[i][j] = min(min(s[i-1][j],s[i-1][j-1]),s[i][j-1]) + 1;
}
}
cout<<s[i-1][j-1]<<"\n";
}
return 0;
}
runtime error occurs. Why?
It seems that you are having some kind of problem with memory allocation.
In your second approach (i.e., the one with local declaration), change:
long long int s[2001][2001];
To:
long long int ** s = new long long int * [2001];
for (i=0;i<2001;i++)
s[i] = new long long int[2001];
This will solve your problem.

TLE in SPOJ ACTIV

I am trying out SPOJ ACTIV. (http://www.spoj.com/problems/ACTIV/) My algorithm works in n log n but still time limit exceeded is coming. Could someone help me please.
We are supposed to find the number of non-empty non-overlapping subsets of activities a person can do in intervals marked (start,end). I am first sorting by start time. Then im doing a binary search on the end in the rest of the array while maintaining the sum in a sum variable(dp)
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <iostream>
#include <algorithm>
#include <utility>
#include <vector>
using namespace std;
typedef pair<long long,long long> p;
vector<long long> ans;
vector<long long> cuml_sum;
int comp(p a,p b){
return a.first<b.first;
}
long long mod(long long sum,long long powe){
return (sum-(sum/powe)*powe);
}
int bins(vector<p> arr,long long start,long long end,long long search){
if(start>end)
return start;
int mid = (start+end)/2;
if(arr[mid].first==search)
return mid;
else if(arr[mid].first<search)
return bins(arr,mid+1,end,search);
else
return bins(arr,start,mid-1,search);
}
void reverse(string s){
int i=0;
int j=s.length()-1;
while(j>=0){
cout<<s[j];
j--;
}
}
void process(long long num)
{
string s="";
int i=0;
while(i<8){
s+=num%10+'0';
num/=10;
if(num==0){
while(i<7){
s+='0';
i++;
}
break;
}
i++;
}
reverse(s);
cout<<"\n";
}
long long func(vector<p> arr)
{
int n=arr.size();
ans[n-1]=1;
long long sum=ans[n-1];
cuml_sum[n-1]=ans[n-1];
for(int i=n-2;i>=0;i--){
int j=bins(arr,i+1,n-1,arr[i].second);
if(j>n-1)
{
ans[j]=0;
cuml_sum[j]=0;
}
ans[i]=1+cuml_sum[j];
cuml_sum[i]=ans[i]+cuml_sum[i+1];
sum+=ans[i];
}
return mod(sum,(long long)pow(10,8));
}
int main(void){
vector<p> arr;
int test,n;
for(int i=0;i<100000;i++){
ans.push_back(0);
cuml_sum.push_back(0);
}
long long a,b;
while(1){
cin>>n;
if(n==-1)
return 0;
for(int i=0;i<n;i++){
cin>>a>>b;
arr.push_back(p(a,b));
}
sort(arr.begin(),arr.end(),comp);
process(func(arr));
arr.clear();
}
return 0;
}

Why doesn't my code generate the prime numbers correctly

The number of prime numbers less than 10,000,000 is 664,579 but my code generates only 664,214. The source of the numbers is https://primes.utm.edu/howmany.html
#include <iostream>
#include <bitset>
#include <vector>
using namespace std;
const int N = 10000001;
bitset<N>num;
vector<int>prime;
inline void sieve()
{
num.flip();
num[0] = num[1] = 0;
for(int i=2;i<N;i++)
if(num[i])
{
prime.push_back(i);
for(long long unsigned j=i*i; j<N;j+=i)
num[j] = 0;
}
}
int main() {
sieve();
cout << prime.size() << endl;
return 0;
}
You have an integer overflow when calculating i*i. The fact that you then assign the result to a long long doesn't make the compiler promote the types before the multiplication.
If I declare i as a long long unsigned int then your program outputs 664579

finding the number of divisors don't know what is going wrong

I am coding to find the number of common divisors of two numbers n and k.
I am implementing it using the approach of finding the GCD g and then finding the number of divisors of the GCD.
However the code compiles but gives a not responding message on running :(
I have blown my head off on this.. can anyone please help in debugging..
Thanks in advance
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<vector>
using namespace std;
vector<bool>p(1000002,true);
long int getgcd(long int a, long int b)
{ if(b == 0)
return a;
else
return getgcd(b, a % b);
}
void prime()
{ int i,j;
for(i=2;i<1000001;i++)
if(p[i])
for(j=i*i;j<1000001;j=j+i)
p[j]=false;
p[0]=false;
p[1]=false;
}
void divfind(long int a, long int b)
{
long int g;
g = getgcd(a,b);
int i,s,j=0,ans=1,num=0;
//short int fo[1000000];
s=(int) sqrt(g);
for(i=2;i<s+1;i++)
if(p[i])
{
while(g%i==0)
{g=g/i;
num++;
}
if(num)
ans*=++num;
num=0;
}
printf("%d\n",ans);
}
int main()
{
prime();
long int n;
int q;
scanf("%ld %d",&n,&q);
while(q--)
{
int t;
long int k;
scanf("%d%ld",&t,&k);
if(t==1)
divfind(n,k);
// else if(t==2)
// divi(n,k);
// else
// nodivi(n,k);
}
return 0;
}
You're running into integer overflows - i*i is only safe up to i=46340 (~2^15*sqrt(2)) with 32 bit integers, e.g:
i i*i
46339 2147302921
46340 2147395600
46341 -2147479015
46342 -2147386332
This leads to undefined behaviour.