Simple fooling questions (press dp bitset)

Question address: https://ac.nowcoder.com/acm/problem/17193
Gossip: This question is a dp of state pressure, but my dp has always been very rubbish, and I haven’t practiced that pressure. Come out, read the solutions of others before doing it. But now I also have some thoughts: I can think of state compression when there are only two states : existence or non-existence .
In fact, I don’t really understand this subject until now, and I still have some records that I don’t understand first.

answer

The most important thing in this topic is the use of bitset. First we need to know what bitset is.
Bitset can be regarded as an array in essence, but each bit can only be 0 or 1, that is, a binary array
that supports bit operations. In this topic, we define two bitset containers, dp and tep. dp saves all the S values ​​of the last time, tmp saves all the S values ​​of this round , and sets the initial value of dp[0] to 1, which is convenient for subsequent transfers.

The next step is the derivation of the recurrence formula.
1. In this problem, you can use a bitset container to store numbers. Record whether the square of each number can exist.
2. The outer loop represents the traversal of n intervals, and the inner loop is used to traverse all possible values ​​in an interval.
3. In-place operations << and | are used for each transfer, because a possible square value is added to the interval, which means that the tmp container needs to update the current value of s. And only need dp<<j*j to indicate that the last value of s has increased by a new amount, and the same result is eliminated during the OR operation and stored in tmp. (However, it is particularly clear why I have not thought about increasing the number of places left by
shifting. ) Then the shift is as follows:

for(int j=l;j<=r;j++) tmp|=dp<<jj;

Code:

#include <bits/stdc++.h>
#define INF 0x3f3f3f3f;
//const int maxn=;
using namespace std;
typedef long long ll;
bitset<1000005>dp,tmp;

int main ()
{
    
    
    //freopen("D:\\input.txt", "r", stdin);
    //freopen("D:\\output.txt", "w", stdout);
    int n,l,r;
    cin>>n;
    dp[0]=1;
    for(int i=1;i<=n;i++){
    
    
        cin>>l>>r;
       tmp.reset();
        for(int j=l;j<=r;j++)
            tmp|=dp<<j*j;
        dp=tmp;
    }
    cout<<dp.count()<<endl;
	return 0;
}


Guess you like

Origin blog.csdn.net/u011612364/article/details/106226407