alice132

 

2026.1.17 作业 - P1118 [USACO06FEB] Backward Digit Sums G/S

题目描述

FJ 和他的奶牛们喜欢玩一个心算游戏。他们将数字从 \(1\)\(N(1 \le N \le 12)\) 按某种顺序写下来,然后将相邻的数字相加,得到一个数字更少的新列表。他们重复这个过程,直到只剩下一个数字。例如,游戏的一种情况(当 \(N=4\) 时)可能是这样的:

    3   1   2   4
      4   3   6
        7   9
         16

FJ 背后,奶牛们开始玩一个更难的游戏,她们试图从最终的总和和数字 \(N\) 中确定起始序列。不幸的是,这个游戏有点超出了 FJ 的心算能力。

编写一个程序来帮助 FJ 玩这个游戏,并跟上奶牛们的步伐。

输入格式

共一行两个正整数 \(n,sum\)

输出格式

输出包括一行,为字典序最小的那个答案。

当无解的时候,请什么也不输出。

输入输出样例 #1

输入 #1

4 16

输出 #1

3 1 2 4

说明/提示

  • 对于 \(40\%\) 的数据,\(1\le N\le 7\)
  • 对于 \(80\%\) 的数据,\(1\le N \le 10\)
  • 对于 \(100\%\) 的数据,\(1\le N \le 12\)\(1\le sum\le 12345\)

题解

方法 1 : 枚举全排列,模拟生成的过程。效率 \(O(n! \times n^2 )\)
方法 2 : 枚举全排列,利用二项式定理确定 \(a_i\) 的系数为 $C_n^i $ ,效率 \(O(n! )\)
方法 3 : 加入剪枝优化。

#include <bits/stdc++.h>
using namespace std;
int c[20][20],n,m,s[20];
int main() {
    c[0][0]=c[1][0]=c[1][1]=1;
    for (int i=2;i<15;i++){
        c[i][0]=c[i][i]=1;
        for (int j=1;j<i;j++) c[i][j]=c[i-1][j-1]+c[i-1][j];
    }
    scanf("%d%d",&n,&m);
    for (int i=0;i<n;i++) s[i]=i+1;
    do{
        int Ans=0;
        for (int i=0;i<n;i++) Ans+=s[i]*c[n-1][i];
        if (Ans==m) {
            cout<<s[0];
            for (int i=1;i<n;i++) cout<<" "<<s[i];
            cout<<endl;
            return 0;
        }
    }while(next_permutation(s,s+n));
    return 0;
}

代码2: 剪枝优化

#include<iostream>
using namespace std;
int n,sum,a[15],c[15],v[20][20];
bool vis[15];
void dfs(int x,int ss){
    if (c[1]!=0) return;
    if(x>n){
        if (ss!=sum) return;
        for(int i = 1; i<=n; i++) c[i] = a[i];
        return ;
    }
    for(int i = 1; i<=n; i++){
        if(vis[i]==0){
            vis[i] = 1; a[x] = i;
            if (ss+i*v[n-1][x]<=sum) dfs(x+1,ss+i*v[n-1][x]);//优化剪枝
            a[x] = 0 ;  vis[i] = 0;
        }
    }
}
int main(){
    cin>>n>>sum;
    v[0][0]=v[1][0]=v[1][1]=1;
    for (int i=2;i<15;i++){
        v[i][0]=v[i][i]=1;
        for (int j=1;j<i;j++) v[i][j]=v[i-1][j-1]+v[i-1][j];
    }
    dfs(1,0);
    if(c[1]==0) { return 0;}
    for(int i = 1; i<=n; i++) cout<<c[i]<<" ";
    cout<<endl;
    return 0;
}

posted on 2026-01-19 20:40  alice_ss  阅读(0)  评论(0)    收藏  举报

导航