UVa10637 - Coprimes(DFS,GCD)

来源:互联网 发布:淘宝店的店铺介绍 编辑:程序博客网 时间:2024/05/17 09:44

Another gloomy day has begun for Shahriar but as usual hisCD player is singing a song of hope. He has a large piece of paper in front ofhim on which he is trying to partition a number into some co-prime numbers byhand in as many ways as possible and surely things are getting out of hiscontrol. He wants to write a program to do this but his limited programmingability is not helping his cause. He has already thought about asking Mr.Kisman to write a code for him but as he has already asked too many favors fromhim he is looking for help from another source. Can you help him? A group ofnumbers is co-prime when the GCD of any two of them is 1. 

 

Shahriar has decided to give a party toall those who will solve this problem so he definitely wants an efficient andintelligent solution so that number of people in the party is small and ofcourse his budget is limited :).

 

Input 

The first line of the input file is anintegerN (0<N<40), which indicates how many sets of inputs arethere. Each of the nextN lines contains one set of input. Each linecontains two integersS (0<S<=100) and t (0<t<=30).So your job is to partitionS into t co-prime numbers.

 

Output 

For each line ofinput you should give several lines of outputs. The description of output foreach line of input is given in the paragraph below:

 

First line shouldbe the serial of the output. Next lines should contain all possible partitionsofS into t co-prime numbers. Each line should containone possible partition. In a partition the printed numbers should be ordered innon-decreasing order and two consecutive numbers should be separated by asingle space. The partitions should be printed in ascending order. Let say onepartition is P1=a1, a2 …,an and another partition isP2=b1, b2,…, bn. ak and bk are not equal andfor all value ofi(0<i<k) ai=bi. Then partition P1>P2 iffak>bk and P1<P2 iff ak<bk. There can be around15000 lines in the output file in total.

 

Sample Input                          Output for SampleInput

2
40 6
8 3

Case 1:

1 1 1 1 1 35

1 1 1 1 5 31

1 1 1 1 7 29

1 1 1 1 11 25

1 1 1 1 13 23

1 1 1 1 17 19

1 1 1 3 5 29

1 1 1 3 11 23

1 1 1 5 9 23

1 1 1 5 11 21

1 1 1 5 13 19

1 1 1 7 11 19

1 1 1 7 13 17

1 1 1 9 11 17

1 1 3 5 7 23

1 1 3 5 11 19

1 1 3 5 13 17

1 1 3 7 11 17

1 1 5 7 9 17

1 1 5 9 11 13

1 3 5 7 11 13

Case 2:

1 1 6

1 2 5

1 3 4

 

题意:给出一个S(1<=s<=100)和t(1<=t<=30),求将s分解成t个数的和(t个数两两互质),输出递增序的所有可能

思路:用gcd求出两个数的最大公约数,刚开始,用递归法超时,换成非递归方式成功。用DFS求出所有可能

#include <cstdio>using namespace std;const int MAXN = 40;int s, t;int a[MAXN];bool input(){    scanf("%d%d", &s, &t);    return true;}int gcd(int n, int m){ while ((n %= m) && (m %= n)); return m + n;}void dfs(int cur, int depth, int sum){    if (cur == depth) {if (sum == 0) {for (int i = 0; i < depth; i++) {if (i) printf(" ");printf("%d", a[i]);}printf("\n");}return;    }     int start;    if (cur == 0) start = 1;    else start = a[cur - 1];        for (int i = start; i <= sum; i++) {        a[cur] = i;        int j;        for (j = 0; j < cur; j++) {            if (gcd(a[j], a[cur]) != 1) break;;        }                if (j >= cur)  dfs(cur + 1, depth, sum - i);    }}void solve(){    dfs(0, t, s);}int main() {#ifndef ONLINE_JUDGE    freopen("d:\\OJ\\uva_in.txt", "r", stdin);#endif       int cas;    scanf("%d", &cas);       for (int i = 1; i <= cas; i++) {        input();        printf("Case %d:\n", i);        solve();    }    return 0;}



0 0