Solution to a problem P2320 [[HNOI2006] Guiguzi purse]

P2320 [HNOI2006] Guiguzi purse

Very interesting a question, the solution of this problem is because of the reason why hair clearer idea of ​​feeling a little qwq

There are two main ways this question:

First, the ideological divide and conquer

For example, to Couchu 1 to 20, if we have been able to Couchu 1 to 10, and then again as long as there is a $ 10 purse, you can Couchu 11 to 20

Similarly, Couchu then to 1-10, 1-5 is required Couchu + a 5-membered purse

So we continue to divide and conquer, then each n / 2 are'll choose the number

If n is odd, such as 21, as long as 1 to 10 Couchu plus a $ 11 to purse

#include<iostream>
using namespace std;
int m,k,a[31]; //2^30>10^9
int main(){
    cin>>m;
    while(m) a[++k]=(m+1)/2,m/=2; //每次m/2都是一定会选的数
    cout<<k<<"\n";
    for (int i=k;i;i--) cout<<a[i]<<" "; //数组递减,倒序输出
}

Second, the binary split

Similar multiple binary knapsack problem decomposition thinking, 2 ^ all less than the number n can be used within 2 ^ 0,2 ^ 1,2 ^ 2 ....... 2 ^ (n-1) represented, and digital least used

For example, to less than the number of all 23 shows, the binary split 23: 0 + 23 = 2 ^ 2 + 2 ^ 1 ^ 2 ^ 2 + 1 = 3 + 8 + 2 + 4 + 8 + 8 (the last 8 remainder after resolution), i.e. with 1,2,4,8,8 may Couchu 1 to 23.

You might ask: 1,2,4,8 in a binary manner can Couchu 1 to 15, but the number between 16 to 22 we will be able 1,2,4,8,8 hash out of it?

In fact, any of a number of 16 to 22 can be expressed in the form 23-x (0 <x <8), and for 0 <x <8 1,2,4,8 Couchu is constant can, in fact, It is to remove it from a few pockets of 1,2,4,8,8.

Similarly, if shown to be less than the number m: Split m = 2 0 2 1 2 2 + ...... + 2 + remainder ^ + ^ + ^ ^ n, for mx (0 <x <remainder), x may be certain 2 ^ 0 + 2 ^ 1 + 2 ^ 2 + ...... + 2 ^ n represented (expressed if not then the x> 2 ^ 0 + 2 ^ 1 + 2 ^ 2 + .. .... + 2 ^ n i.e., x> = 2 ^ (n + 1), then x can continue to split, inconsistent with the intended title)

Moreover, you should note that there are not two of the same purse containing gold is greater than 1, two 8 for 23, 7, 9 can be changed (due to Couchu sure to use the number 1 is on, when we need 8 when used, direct use can be 7 + 1, if needed 1,7 + 1 + 1, like 9 directly, of course, better to have special judge). Since 2 ^ n is incremented, it is up to the remainder of a number of identical, special sentence can be, without sorting.

Code long mainly because some special judge, however, seems to rule the score slightly faster qwq?

#include<cstdio>
using namespace std;
int m,n,a[31];
bool flag; //是否有余数?
int main() {
    scanf("%d",&m);
    for (int x=1; x<=m; x<<=1)
        a[++n]=x,m-=x; //二进制拆分
    n++;
    if (m) a[n]=m; //余数
        else flag=1; 
    printf("%d\n",n-(flag==1)); //没有余数就-1
    for (int i=1; i<n; i++) {
        if (!flag) { //如果余数还没输出,则判断当前位置是否该输出余数了
            if (a[i]==a[n]) printf("%d ",a[n]-1),a[i]++,flag=1; //余数与一个数相同
            else if (a[n]<a[i]) printf("%d ",a[n]),flag=1; //没有数与余数相同,按顺序输出
        }
        printf("%d ",a[i]);
    }
    if (!flag) printf("%d",a[n]); //如果余数最大
}

Guess you like

Origin www.cnblogs.com/Randolph68706/p/11616328.html