topcoder-srm701-div2-900 game \ Calculate the number of Bits 1 \dp\ state compression

Source: Internet
Author: User

Borrow the QLS translation.

Now there are n stones, A and B take the stones in turn, a first, each time up to a maximum of M stones, the last one to win the stone, but someone if the stone when the remaining stones in the binary representation of the number of odd number 1, this person lost
Given N and M, ask who wins
N<=5e8, m<=50
TL 2s before I was never exposed to the game of the first to popularize the basic knowledge of the game. Win the state, will be defeated, and win points and must be defeated first there must be a word to see clearly, that is "must" word is to win and not, victory on the line, the word is very key

, a point is p-position condition is that his precursor is a winning state

One point is that n-position requires all of his successors to be undefeated (otherwise he can't win, remember.) is to win)

So we can get that the rule that marks a point is to observe all subsequent nodes of a point that is not currently marked, if its successors are all

Reached the winning state, then this point must be a must-fail state, we are marked as a must, if its successor node is at least one point is a must-fail state, then

The current point must be a winning state, because if there is a way to win, as long as there is, we will definitely go to choose him.

After knowing this, it's almost there.

First of all.. There are n stones at the beginning, but each of us will not know how the current decision is optimal, since the state of n Stones starts,

The state of the successor node without a point is clear, we need to find at least one point with a definite state to continue our work

What we need to do at this time is to find the final state in this game scenario and what is the final state. First, the victory has been divided,

Second, from this state can no longer move, the game can not go on.

So this problem, there are two final state, first when you face the stone, it has left 0, the game is over, you can not do anything, and you lost the game

Second, when you face this heap of stones, his number is written in binary form after an odd number of 1, and the topic said, if the current move after the result is an odd number of 1, then

The person who moves will lose, so in other words, when you just face this odd number of 1 o'clock, you don't have to do anything because the last person has lost (as defined by the game in the title)

So at least we have to find at least one point with a definite state in the definition, and when we start from this state of n stones, we find that if its sons have no definite

State, then I can only find the sons of his son, then we find that this is actually a recursive process, and eventually we will find the leaf node (point with definite state)

Then we go back to the basics of game theory, because we know that after all the subsequent nodes have a definite state, then we can easily infer

What is the state of their father node

intDfsintNintMintDEP) {    if(ans[n]!=-1) {        returnAns[n]; }    if(n==0){        returnans[n]=0;//lose when the end state is zero    }    if(Count (n)%2==1){        returnans[n]=1;//the current number of bits is odd} Registerinti; intRes=dfs (n1, m,dep+1);  for(i=2; i<=m;++i) {        if(n-i>=0) {res&=dfs (n-i,m,dep+1); }    }    if(res==1){        returnans[n]=0; }    Else{        returnans[n]=1; }}

The above is the version of the recursive program

After we know the process, we find that the process of finding a leaf node (a point with a definite state) at the beginning is superfluous.

Because we know what knowledge to use to find the leaf nodes, that is, the meaning of the final state is clear.

So we can go back directly from the bottom of the recursive tree.

voidSolveintNintm) {    inti,j; intres=0; intDp[m];  for(i=1; i<=m;++i) {Dp[i]=1; }     for(i=1; i<=n;++i) {        //Cur=res;         for(j=2; j<=m;++j) {            if(n-j>0) {res&=Dp[j]; }        }        if(res==1) {res=0; }        Else{res=1; }        if(Count (i)%2==1) {res=1; }         for(j=m;j>=2;++j) {Dp[j]=dp[j-1]; } dp[1]=Res; }}

This is the version of the recursive program.

Why do you want to open the M-size DP array, because, at each stage of the game, we have a choice of M, select a number in the 1~m, take the corresponding number of stones

If we can take it, we'll talk about it.

And there's another way to analyze it, because you're pushing up from the bottom of the recursive tree, and you need to know what all the child nodes are on that point.

Or how to find all of its child nodes, then we know that because you make a maximum of M-decisions at each stage (there will be fewer stone numbers than m decisions)

So through M we can find the state of its successors, because each time we only use the M state, so we only have this m state, each iteration can be

How do we iterate? We are going to analyze the recursive tree, each time this m state is what state (I have to use which M state), this problem is just the regular, constantly used to calculate the iteration

The old state on the line, you must draw a picture.

Come to this step. We notice that the number of my DP array, not zero is 1, and M is also small, maximum 50, then long Long is able to save, here is a pit

That is ll p= (1<<50); Since 1 is integral by default, it must be written ll p= (1LL<<50)

So we consider using a long long to press the M-bit, for state compression. , then how can I consider the update of my m status? Do not worry.. We use bit arithmetic

Using the left shift operation, you can achieve the effect of saving the previous bit with the following bit. But in that case, the number is getting bigger, not the M-bit. It's going to explode. So

We do this with the number of a M-bit all-in-one number with the pressure level, so that the number of 0 of the high position of the M-bit full 1 is truncated to a position that is not 1 of the M-bit.

Then the last one uses or operations to update the state. This replaces the DP array above.

voidTestintNintm) {ll Allwin= (1ll<<m)-1; ll Nowstate=Allwin; Registerinti,j;  for(i=0; i<=n;++i) {        if(Count (i) &1|| nowstate!=Allwin) {Res=1; }        Else{res=0; } nowstate= ((nowstate<<1) &allwin) |Res; }}

Here the count (int v) function is used to calculate the number of binary 1, which is obviously the time complexity is NLOGN

For the data in the topic, this will definitely timeout.

So we're going to speed up the calculation for count (n)

And then what.. We notice that the number of N in the topic does not exceed int, then int has 32 bits, and we can use the idea of splitting

Divide it into two halves, then half is 1<<16. , so. We just preprocess the 0~ (1<<16)-1 (16 1) and the number of each of these numbers is 1.

((pre[i>>16]+pre[i& ((1<<16)-1)]) &1) Let's take a look at this equation.

The first half of the sentence is said, take the high 16 bits of I, is clearly in the target of more than 16 bits I, if I was not enough 16 bits, then we know pre[0]=0;

So the latter sentence is saying, take out the low 16 bits of I.

And then we'll be able to preprocess this value quickly.

We also used a __builtin_popcount, (note that there are two underscores in front ...) ), this is a built-in function: Do not need a header file, this function is still the thief fast.

He can quickly figure out how many bits 1 of a number.

In addition: string is preceded by std::

Put the code below.

#include <iostream>#include<cstdio>#include<string.h>#include<time.h>#definell Long Longclassthuemorsegame{ Public:    intpre[1<< -]; STD::string Get(intNintm) {    inti; intres=0; ll Allwin= (1ll<<m)-1; ll Nowstate=Allwin;  for(i=0;i< (1<< -);++i) {Pre[i]=__builtin_popcount (i); }     for(i=0; i<=n;++i) {        if(((pre[i>> -]+pre[i& ((1<< -)-1)]) &1)|| nowstate!=Allwin) {Res=1; }        Else{res=0; } nowstate= ((nowstate<<1) &allwin) |Res; }    //I start from 1, the nowstate is all 1, is wrong, because there is a 0 of the must-fail state//so start from scratch and initialize    return(nowstate&1)?"Alice":"Bob"; }};intMain () {intst,ed; intn,m; scanf ("%d%d",&n,&m);    Thuemorsegame p; St=clock (); STD::stringAns=p.Get(N,M); Ed=clock (); Std::cout<<ans<<"Time :"<< (Double) (ed-st)/clocks_per_sec<<"s"<<Std::endl; return 0;}

topcoder-srm701-div2-900 game \ Calculate the number of Bits 1 \dp\ state compression

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.