noip第22课作业

时间:2022-09-25 21:57:39

1.   数字分解

【问题描述】

任何一个大于1的自然数n,总可以拆分成若干个小于n的自然数之和,当n等于5时有6种拆分方法:

5=1+1+1+1+1

5=1+1+1+2

5=1+1+3

5=1+2+2

5=1+4

5=2+3

输入:一行包含一个正整数n(1<n<10)。

输出:先将拆分方案输出,然后再输出拆分的方案数。

【输入样例】

5

【输出样例】

5=1+1+1+1+1

5=1+1+1+2

5=1+1+3

5=1+2+2

5=1+4

5=2+3

total=6

#include <iostream>
using namespace std;
int a[10001] = {1},n,total;

//输出函数
void print(int t) {  //拆成t项
    cout << n << "=";
    for(int i = 1; i <= t-1; i++) {
        cout << a[i] << "+";
    }
    cout << a[t] << endl;
    total++;
}

void find(int m,int t) {
    for(int i = a[t-1]; i<=m; i++) {
        if(i < n) {
            a[t] = i;  //保存当前拆分的i
            m-=i;
            if(m ==0) {   //拆分结束,输出结果
                print(t);
            } else {
                find(m,t+1);
            }
            m+=i;  //回溯:加上拆分的数,以便产生所有可能的拆分
        }
    }
}
int main() {
    cin >> n;
    find(n,1);
    cout << "total=" <<total << endl;
    return 0;
}

2.放苹果

【问题描述】

把M个同样的苹果放在N个同样的盘子里,允许有的盘子空着不放,问共有多少种不同的分法?(用K表示)5,1,1和1,5,1 是同一种分法。

输入:第一行是测试数据的数目t(0 <= t <= 20)。以下每行均包含二个整数M和N,以空格分开。1<=M,N<=10。

输出:对输入的每组数据M和N,用一行输出相应的K。

【输入样例】

1

7 3

【输出样例】

8

/*
m个苹果放在n个盘子中,那么定义函数为apple(m,n):

  1.m=0,没有苹果,那么只有一种放法,即apple(0,n)=1

  2.n=1,只有一个盘中,不论有或者无苹果,那么只有一种放法,apple(m,1)=1

  3.n>m,和m个苹果放在m个盘子中是一样的,即apple(m,n)=apple(m,m)

  4.m>=n,这时分为两种情况,一是所有盘子都有苹果,二是不是所有盘子都有苹果。
  不是所有盘子都有苹果和至少有一个盘子空着是一样的,即=apple(m,n-1)。所
  有盘子都有苹果,也就是至少每个盘子有一个苹果,m个苹果中的n个放在n个盘子中,
  剩下的m-n个苹果,这和m-n个苹果放在n个盘子中是是一样的,即=apple(m-n, n)。
  这时,apple(m,n)=apple(m-n, n)+apple(m,n-1)。
*/
#include<iostream>
using namespace std;
int apple(int m,int n) { //m个苹果放到n个盘子里
    if(m < 0 || n <1){
        return 0;
    } 
    //判断只有一个方法放苹果的情况
    if(m==0 || n==1){
        return 1;
    } 
    //否则判断苹果数是否少于盘子数,如果少,那么肯定有n-m个空盘子
    //所以只要做把m个苹果放到m个盘子里
    else if(m<n) {
        return apple(m,m);
    }
    //m>=n的情况 : 
    //所有的盘子都有苹果,即只要把m-n个苹果放到n个盘子里
    //不是所有盘子都有苹果和至少有一个盘子空着是一样的,即=apple(m,n-1)
    else {
        return apple(m-n,n)+apple(m,n-1);
    }
    
}
int main() {
    int t;
    cin>>t;
    while(t--) {
        int m,n;
        cin>>m>>n;
        cout<<apple(m,n)<<endl;
    }
}

1.全排列

【问题描述】

输入一个数字N(1<N<10),输出所有使用1到N数字组成的N位数(每个数字只能使用一次)。

【样例输入】

3

【样例输出】

123

132

213

231

312

321

#include <iostream>
using namespace std;
int a[10],book[10],n;

//站在第step个盒子面前
void dfs(int step){
    int i;
    if(step == n+1){
        //输出一种全排列
        for(i = 1;i<=n;i++){
            cout << a[i];
        } 
        cout << endl;
        return;  //返回之前的一步,最近一次调用dfs函数的地方 
    }
    
    //站在第step个盒子面前, 遍历1到n一一去尝试 
    for(i = 1;i <= n;i++){
        //判断该数字是否还未被使用 
        if(book[i] == 0){
            a[step] = i;
            book[i] = 1;//表示已被使用
            
            //接下里走到step+1的盒子面前,做同样的操作
            dfs(step+1);
            book[i]=0;//一定要将刚才尝试的数字收回,才能进行下一次的尝试 
        }
    } 
    
    return; 
}
int main(){
    cin >> n;
    dfs(1);
    return 0;
}

2.分为互质组

【问题描述】

给定n个正整数,将他们分组,使得每组中任意两个数互质。至少要分成多少个组?

输入:第一行是一个正整数n,1<=n<=10;第二行是n个不大于10000的正整数。

输出:一个正整数,即最少需要的组数。

【输入样例】

6

14 20 33 117 143 175

【输出样例】

3

#include <iostream>
using namespace std;
int a[20],b[20],n;
int ans;
//定义gcd函数求两个数的最大公约数
int gcd(int a,int b) {
    if(b==0) {
        return a;
    } else {
        return gcd(b,a%b);
    }
}
void dfs(int x,int y) { //x:第几个数  y:已有多少组
    //递归终止条件
    if(x>n) {
        ans = y;
        return;
    }
    bool flag = false;
    //判断当前值是否是属于已有组
    for(int i = 1; i <=y; i++) {
        bool pd = true;
        for(int j = 1; j < x; j++) {
            //第j个元素属于第i组,并且第x个元素与第j个元素不是互为质数,则a[x]不属于第i组
            if(b[j] == i && gcd(a[x],a[j]) != 1 ) {
                pd = false;
                break;
            }
        }
        if(pd == true) { //第x个元素与第i组的所有元素都互为质数
            flag = true;
            //第x个元素属于第i组
            b[x] = i;
            //接着判断下一个元素(第x+1个元素)是否属于已有的y组
            dfs(x+1,y);
            //将b[x]重新赋值为0
            b[x]=0;
        }
    }
    if(flag == false) {
        //如果当前值不属于已有的任何一组  需要新开一个组别
        //第x个元素属于第y+1组
        b[x] = y+1;
        //接着判断下一个元素(第x+1个元素)是否属于已有的y+1组
        dfs(x+1,y+1);
        b[x] = 0;
    }
}
int main() {
    cin >> n;
    for(int i = 1; i <=n; i++) {
        cin >> a[i];
    }
    //初始化b数组,第1个元素属于第1组
    b[1] = 1;
    dfs(2,1);
    cout << ans << endl; 
    return 0;
}