count the number of products of all possible subarrays where product should be divisible by four or it is odd - c++

i tried to count the number of products which are odd or divisible by 4 , generated by all possible sub-arrays but my implementation get O(n^2).... i need in O(n) time . I also tried to get some pattern but cant found it
here is my code
#include<bits/stdc++.h>
#define lli long long int
using namespace std;
int main()
{
lli testcases,x,M=1000000007;
cin>>testcases;
for(x=0;x<testcases;x++){
lli n,i,j,temp,count1=0;
cin>>n;
vector<lli>v;
for(i=0;i<n;i++){
cin>>temp;
v.push_back(temp);
}
for(i=0;i<n-1;i++){
if(v[i]%2!=0 || v[i]%4==0){
++count1;
}
temp=v[i];
for(j=i+1;j<v.size();j++){
temp*=v[j];
if(temp%2!=0 || temp%4==0){
++count1;
}
}
}
if(v[n-1]%2!=0 || v[n-1]%4==0){
++count1;
}
cout<<count1<<"\n";
count1=0;
}
return 0;
}
thanks in advance !

The question is asking for the number of subarrays whose product is odd (zero factors of two) or a multiple of four (at least two factors of two).
We can also invert this: take the number of subarrays (2**N) and subtract the number of subarrays that have exactly one factor of two.
So, first preprocess the array and replace every number with its factors of two (ie 7 becomes 0, 8 becomes 3, etc).
The question is then "how many subarrays sum to exactly one", which has a known solution.

this question is directly linked to ( april long challenge) from codechef. i don't think its a good idea to ask directly here before the closing of contest (3:00 pm , 13/04/2020).
please obey rules and regulations of codechef. you can check out at this link if you don't believe my words.
https://www.codechef.com/APRIL20B/problems/SQRDSUB or directly visit codechef april challenge (squared subsequence).

Related

Reaching from first index to last with minimum product without using Graphs?

Solving this problem on codechef:
After visiting a childhood friend, Chef wants to get back to his home.
Friend lives at the first street, and Chef himself lives at the N-th
(and the last) street. Their city is a bit special: you can move from
the X-th street to the Y-th street if and only if 1 <= Y - X <= K,
where K is the integer value that is given to you. Chef wants to get
to home in such a way that the product of all the visited streets'
special numbers is minimal (including the first and the N-th street).
Please, help him to find such a product. Input
The first line of input consists of two integer numbers - N and K -
the number of streets and the value of K respectively. The second line
consist of N numbers - A1, A2, ..., AN respectively, where Ai equals
to the special number of the i-th street. Output
Please output the value of the minimal possible product, modulo
1000000007. Constraints
1 ≤ N ≤ 10^5 1 ≤ Ai ≤ 10^5 1 ≤ K ≤ N Example
Input: 4 2 1 2 3 4.
Output: 8
It could be solved using graphs based on this tutorial
I tried to solve it without using graphs and just using recursion and DP.
My approach:
Take an array and calculate the min product to reach every index and store it in the respective index.
This could be calculated using top down approach and recursively sending index (eligible) until starting index is reached.
Out of all calculated values store the minimum one.
If it is already calculated return it else calculate.
CODE:
#include<iostream>
#include<cstdio>
#define LI long int
#define MAX 100009
#define MOD 1000000007
using namespace std;
LI dp[MAX]={0};
LI ar[MAX],k,orig;
void cal(LI n)
{
if(n==0)
return;
if(dp[n]!=0)
return;
LI minn=MAX;
for(LI i=n-1;i>=0;i--)
{
if(ar[n]-ar[i]<=k && ar[n]-ar[i]>=1)
{
cal(i);
minn=(min(dp[i]*ar[n],minn))%MOD;
}
}
dp[n]=minn%MOD;
return;
}
int main()
{
LI n,i;
scanf("%ld %ld",&n,&k);
orig=n;
for(i=0;i<n;i++)
scanf("%ld",&ar[i]);
dp[0]=ar[0];
cal(n-1);
if(dp[n-1]==MAX)
printf("0");
else printf("%ld",dp[n-1]);
return 0;
}
Its been 2 days and I have checked every corner cases and constraints but it still gives Wrong answer! Whats wrong with the solution?
Need Help.
Analysis
There are many problems. Here is what I found:
You restrict the product to a value inferior to 100009 without reason. The product can be way higher that that (this is indeed the reason why the problem only asked the value modulo 1000000007)
You restrict your moves from streets whose difference in special number is K whereas the problem statement says that you can move between any cities whose index difference is inferior to K
In you dynamic programming function you compute the product and store the modulo of the product. This can lead to a problem because the modulo of a big number can be lower than the modulo of a lower number. This may corrupt later computations.
The integral type you use, long int, is too short.
The complexity of your algorithm is too high.
From all these problems, the last one is the most serious. I fixed it by changing the whole aproach and using a better datastructure.
1st Problem
In your main() function:
if(dp[n-1]==MAX)
printf("0");
In your cal() function:
LI minn=MAX;
You should replace this line with:
LI minn = std::numeric_limits<LI>::max();
Do not forget to:
#include <limits>
2nd Problem
for(LI i=n-1;i>=0;i--)
{
if(ar[n]-ar[i]<=k && ar[n]-ar[i]>=1)
{
. . .
}
}
You should replace the for loop condition:
for(LI i=n-1;i>=n-k;i--)
And remove altogether the condition on the special numbers.
3rd Problem
You are looking for the path whose product of special numbers is the lowest. In your current setting, you compare path's product after having taken the modulo of the product. This is wrong, as the modulo of a higher number may become very low (for instance a path whose product is 1000000008 will have a modulo of 1 and you will choose this path, even if there is a path whose product is only 2).
This means you should compare the real products, without taking their modulo. As these products can become very high you should take their logarithm. This will allow you to compare the products with a simple double. Remember that:
log(a*b) = log(a) + log(b)
4th Problem
Use unsigned long long.
5th Problem
I fixed all these issues and submitted on codechef CHRL4. I got all but one test case accepted. The testcase not accepted was because of a timeout. This is due to the fact that your algorithm has got a complexity of O(k*n).
You can achieve O(n) complexity using a bottom-up dynamic programming approach, instead of top-down and using a data structure that will return the minimum log value of the k previous streets. You can lookup sliding window minimum algorithm to find how to do.
References
numeric_limits::max()
my own codechef CHRL4 solution: bottom-up dp + sliding window minimum

Wrong result for code doing dynamic programming in C++

I am solving a dp problem .The problem is that I have N dices; each of them has K faces numbered from 1 to K. Now I have arranged the N dices in a line. I can rotate/flip any dice if I want. How many ways I can set the top faces such that the summation of all the top faces equals S?
Now I am given N, K, S; I have to calculate the total number of ways.It is worthy of mention I have to print the result modulo 100000007.I have tried to solve this problem and write a code for this one but my code doesn't work for this case:800 800 10000 why? I can't understand .Can anyone explain the cause for which my code doesn't work. My code is here:
#include<iostream>
#include<cstdio>
#include<cmath>
#include<memory.h>
#define M 100000007
#define ull unsigned long long
using namespace std;
ull n,K,s,dp[1001][1001];
ull fnc(int num,int sum,int k)
{
ull temp;
if(num==0){
if(sum==0) return 1;
else return 0;
}
if(dp[num][k]!=-1)
return dp[num][k];
for(int i=1;i<=K;i++)
{
temp=temp%M+fnc(num-1,sum-i,i)%M;
}
return dp[num][k]=temp%M;
}
int main()
{
int T;
cin>>T;
for(int t=1;t<=T;t++)
{
cin>>n>>K>>s;
memset(dp,-1,sizeof(dp));
printf("Case %d: %lld\n",t,fnc(n,s,0));
}
return 0;
}
You used the wrong subscripts for dp.
Consider how many ways you can get 800 dice, each with numbers from 1 to 800,
to have the sum 10000 if you make the number 1 uppermost on the first die
and you make 4 uppermost on the second die.
Now consider how many ways to have the sum 10000 if you make 2 uppermost on the first die
and 3 uppermost on the second die.
Those two quantities are the same: each is the number of ways to get 798 dice (with numbers 1 to 800) to have the sum 99995. That is the kind of quantity you want to memoize.
But you have not even allocated enough space in dp to store this kind of partial answer.
I also have to wonder why you are using unsigned long long rather than just unsigned long, since your answer is to be given modulo 100000007. You should never have to
work with numbers that are even near the maximum value of a signed long.
According to http://linux.die.net/man/3/memset :
The memset() function fills the first n bytes of the memory area pointed to by s with the constant byte c.
Note it doesn't say "the constant unsigned long long c".
You have the value k and K defined in the same scope, which is infuriating.
You hard coded 1001 and -1 instead of giving them proper soft coded variable names.
Most of your variable names are 1 character long.
You have persistent behavior in a return statement.
You have absolutely nothing checking if the values of k, K, and num are within the proper range of dp, which is partially a consequence of hard coding 1001.
Spacebar is your friend, writingcodelikethisthatwehavetoreadisannoying.

Optimization algorithm with numbers

Given a list of numbers in increasing order and a certain sum, I'm trying to implement the optimal way of finding the sum. Using the biggest number first
A sample input would be:
3
1
2
5
11
where the first line the number of numbers we are using and the last line is the desired sum
the output would be:
1 x 1
2 x 5
which equals 11
I'm trying to interpret this https://www.classle.net/book/c-program-making-change-using-greedy-method using stdard input
Here is what i got so far
#include <iostream>
using namespace std;
int main()
{
int sol = 0; int array[]; int m[10];
while (!cin.eof())
{
cin >> array[i]; // add inputs to an array
i++;
}
x = array[0]; // number of
for (int i; i < x ; i++) {
while(sol<array[x+1]){
// try to check all multiplications of the largest number until its over the sum
// save the multiplication number into the m[] before it goes over the sum;
//then do the same with the second highest number and check if they can add up to sum
}
cout << m[//multiplication number] << "x" << array[//correct index]
return 0;
}
if(sol!=array[x+1])
{
cout<<endl<<"Not Possible!";
}
}
Finding it hard to find an efficient way of doing this in terms of trying all possible combinations starting with the biggest number? Any suggestions would be greatly helpful, since i know im clearly off
The problem is a variation of the subset sum problem, which is NP-Hard.
An NP-Hard problem is a problem that (among other things) - there is no known polynomial solution for it, thus the greedy approach of "getting the highest first" fails for it.
However, for this NP-Hard problem, there is a pseudo-polynomial solution using dynamic programming. The problem where you can chose each number more then once is called the con change problem.
This page contains explanation and possible solutions for the problem.

code to solve the "Theater Row" brain teaser

I was reading a book called "Fifty Challenging Problems in Probability", which is filled with lots of probability-related brain teasers. I wasn't able to solve one of the problems there, and wasn't able to understand the solution, either. So, I was writing a code to get a better feeling. Here is the original problem.
The Theater Row:
Eight elegible bachelors and seven beautiful models happen randomly to have purchased single seats in the same 15-seat row of a theater. On the average, how many pairs of adjacent seats are ticketed for marriageable couples?
And here is my code, getting an average number of adjacent pairs out of 100 random sampling:
#include <iostream>
#include <vector>
#include <cstdlib>
#include <algorithm>
#include <numeric>
using namespace std;
// computes the probability for the "theater row" problem
// in the book fifty challenging probabilty problems.
vector<int> reduce(vector<int>& seats); // This function reduces a sequence to a form
// in which there is no adjacent 0's or 1's.
// *example: reduce(111001)=101*
int main()
{
srand(time(0));
int total=15;
int Num=100;
int count0=0; // number of women
int count1=0; // number of men
vector<int> seats; // vector representing a seat assignment,
// seats.size()=total
vector<int> vpair; // vector that has number of adjacent pairs
// as its element, size.vpair()=Num
for (int i=0; i<Num; ++i) {
count0=count1=0;
while ((count1-count0)!=1) {
count0=count1=0;
seats.clear();
for (int j=0; j<total; ++j) {
int r=rand()%2;
if (r==0)
++count0;
else
++count1;
seats.push_back(r);
}
}
for (int k=0;k<seats.size();++k)
cout<<seats[k];
reduce(seats);
for (int k=0;k<seats.size();++k)
cout<<" "<<seats[k];
vpair.push_back(seats.size()-1); // seats.size()-1 is the number
// of adj pairs.
cout<<endl;
}
double avg=static_cast<double>(accumulate(vpair.begin(),vpair.end(),0))/vpair.size();
cout<<"average pairs: "<<avg<<endl;
return 0;
}
vector<int> reduce(vector<int>& seats)
{
vector<int>::iterator iter = seats.begin();
while (iter!=seats.end()) {
if (iter+1==seats.end())
++iter;
else if (*iter==*(iter+1))
iter=seats.erase(iter);
else
++iter;
}
return seats;
}
The code generates random series of 0's (representing women) and 1's (men). It then "reduces" the random sequence so that there are no repeating 0's or 1's. For example, if the code generates a random sequence of 011100110010011 (which has 7 adjacent pairs), the sequence is reduced to 01010101. In the reduced format, to figure out the number of adjacent pairs, you just need to get the "size-1".
Here are my questions.
The answer to the question (according to the book) is 7.47, while I get an average of about 7 or so from the code. Does anybody see where the discrepancy originates?
My code seems quite inefficient sometimes. Is it due to the way I generate a random sequence? (As you can see, to generate a random sequence of 8 men and 7 women, I keep asking for a random sequence of size 15 until it happens to have 8 men(or "1") and 7 women(or "0"). Is there a better way to produce a random sequence when there is a constraint like this?
I am not so proficient when it comes to programming. I'd appreciate any comments. Thank you for you help!!
This Problem is hilarious.
There are 1307674368000 possible combinations.
There is 203212800 combinations where 1 couple gets together.
But there are 3048192000 combinations where 2 couples get together.
Think the key to this problem would be doing a smaller scale problem first and use that info to create your answer. This is just a expected value problem.
Edit: Instead of running simulations, you could just get the exact answer using expected value, will have to think harder, but you also will be exact. I'll take a little bit to see if I can come up with the exact answer and post it.
Important Edit(Read):
Does your code account for if you if you get more than 8 0's or 8 1's. Sense you only can at most have 8 men and 7 women, then it should automatically feel the rest with the left over symbols.

Is there any trick to handle very very large inputs in C++?

A class went to a school trip. And, as usually, all N kids have got their backpacks stuffed with candy. But soon quarrels started all over the place, as some of the kids had more candies than others. Soon, the teacher realized that he has to step in: "Everybody, listen! Put all the candies you have on this table here!"
Soon, there was quite a large heap of candies on the teacher's table. "Now, I will divide the candies into N equal heaps and everyone will get one of them." announced the teacher.
"Wait, is this really possible?" wondered some of the smarter kids.
Problem specification
You are given the number of candies each child brought. Find out whether the teacher can divide the candies into N exactly equal heaps. (For the purpose of this task, all candies are of the same type.)
Input specification
The first line of the input file contains an integer T specifying the number of test cases. Each test case is preceded by a blank line.
Each test case looks as follows: The first line contains N : the number of children. Each of the next N lines contains the number of candies one child brought.
Output specification
For each of the test cases output a single line with a single word "YES" if the candies can be distributed equally, or "NO" otherwise.
Example
Input:
2
5
5
2
7
3
8
6
7
11
2
7
3
4
Output:
YES
NO
The problem is simple but the case is that SPOJ judges are using very very large inputs. I have used unsigned long long as datatype, yet it shows wc..
Here's my code:
#include<iostream>
using namespace std;
int main()
{
unsigned long long c=0,n,k,j,testcases,sum=0,i;
char b[10000][10];
cin>>testcases;
while(testcases-->0)
{
sum=0;
cin>>n;
j=n;
while(j-->0)
{
cin>>k;
sum+=k;
}
if(sum%n==0)
{
b[c][0]='Y';b[c][1]='E';b[c][2]='S';b[c][3]='\0';
c++;
}
else
{
b[c][0]='N';b[c][1]='O';b[c][2]='\0';
c++;
}
}
for(i=0;i<c;i++)
cout<<"\n"<<b[i];
return 0;
}
Easy. Don't add up the number of candies. Instead, keep a count of kids, a count of candies per kid. (CCK), and a count of extra candies (CEC. When you read a new line, CK += 1; CEC += newCandies; if (CEC > CK) CCK += (CEC / CK); CEC %= CK;
Does a line like this not concern you?
b[c][0]='Y';b[c][1]='E';b[c][2]='S';b[c][3]='\0';
Would it not be simpler to write??
strcpy(b[c], "YES");
You can do this question without summing all the candies. Just calculate the remainder off each child's heap (which will be smaller than N). This way, the number won't grow too large and overflow.
I won't write out a solution since this is a contest problem, but if you're stuck I can give some more hints.
If you have input that is larger than unsigned long long, then they probably want you to implement custom functions for arbitrary-precision arithmetic (or the problem can be solved without using the large integers). If the input fits the largest native integer type, but your algorithm requires larger integer, it's most likely time to think about a different algorithm. :)
If you're reading in from cin, you can only read in values that will fit into some sort of integer variable. It's possible that the sum would overflow.
However, you don't have to add the numbers up. You can add the remainders (from dividing by N) up, and then see if the sum of the remainders is N.