P1118 [USACO06FEB]数字三角形 Backward Digit Su

题解

可以递推出初始的系数组,然后遍历所有的排列并计算就可以了。
用stl会超时,需要优化。我们在计算累乘的过程中 若发现此位置算上后 cur_sum已经大于目标sum时
那么在对后面的数做permutation就无用了 全部都会大于sum,所以可以直接跳过。
跳的方式是 把第i位到末尾的数全部从大到小排序,那么下次permutaion就会改变当前i位。
这是根据permutaion的计算方式做的优化。


Code

#include <iostream>
#include <cstdio>
#include <fstream>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <algorithm>
using namespace std;
int n,m,fin;
int s[13];
int cot[2][13];
void cal(){
    int tar,ori;

    for(int i=1;i<n;i++){
        tar = i%2;
        ori = 1-tar;
        memset(cot[tar],0,sizeof(int)*n );
        for(int j=1;j<=i;j++){
            cot[tar][j] += cot[ori][j];
            cot[tar][j+1] += cot[ori][j];
        }
    }
}

int main(void){

    int sum;
    cin>>n>>sum;

    for(int i=1;i<=n;i++) s[i] = i;
    cot[0][1] = 1;
    cal();

    fin = 1-n%2;// final chosen cot

    int cur_sum;
    do{
        cur_sum = 0;
        for(int i=1;i<=n;i++){
            cur_sum+= cot[fin][i] * s[i];
            if(cur_sum > sum){
                sort(s+i, s+1+n,greater<int>());
                break;
            }
        }

        if(sum == cur_sum)
        {

            for(int i=1;i<=n;i++){
                cout<<s[i]<<" "; 
            }
            break;
        }
    }while(next_permutation(s+1,s+1+n));


    return 0;
}

猜你喜欢

转载自blog.csdn.net/smmyy022/article/details/81506705