1 条题解

  • 0
    @ 2026-9-30 12:58:12

    C++ :

    
    #include <cstdio>
    /* 最终结果 = Σ C(n-1,i) * p[i]。从左到右按值升序 DFS,
       用「剩余系数 × 剩余可用值」的上下界剪枝,首个解即字典序最小。 */
    static int n, used[13], perm[13], found;
    static long long target, coef[13];
    void dfs(int p, long long cur){
        if(found) return;
        if(p == n){ if(cur == target) found = 1; return; }
        int avail[13], ac = 0;
        for(int v = 1; v <= n; v++) if(!used[v]) avail[ac++] = v;   /* 升序 */
        long long cs[13];
        int k = n - p;
        for(int i = 0; i < k; i++) cs[i] = coef[p + i];
        for(int i = 0; i < k; i++)
            for(int j = i + 1; j < k; j++)
                if(cs[i] > cs[j]){ long long t = cs[i]; cs[i] = cs[j]; cs[j] = t; }
        long long mn = 0, mx = 0;
        /* 重排不等式:大系数配小值最小,大系数配大值最大 */
        for(int i = 0; i < k; i++) mn += cs[k - 1 - i] * avail[i];
        for(int i = 0; i < k; i++) mx += cs[i] * avail[i];
        if(cur + mn > target || cur + mx < target) return;
        for(int i = 0; i < ac; i++){
            int v = avail[i];
            used[v] = 1; perm[p] = v;
            dfs(p + 1, cur + coef[p] * v);
            used[v] = 0;
            if(found) return;
        }
    }
    int main(){
        long long sum;
        if(scanf("%d %lld", &n, &sum) != 2) return 0;
        target = sum;
        coef[0] = 1;
        for(int i = 1; i < n; i++) coef[i] = coef[i - 1] * (n - i) / i;
        for(int i = 1; i <= n; i++) used[i] = 0;
        found = 0;
        dfs(0, 0);
        if(found){
            for(int i = 0; i < n; i++) printf("%d%c", perm[i], i + 1 == n ? '\n' : ' ');
        }
        return 0;
    }
    
    
    • 1

    信息

    ID
    2835
    时间
    1000ms
    内存
    256MiB
    难度
    (无)
    标签
    递交数
    0
    已通过
    0
    上传者