HUNNU11394:Do It Wrong, Get It Right

http://acm.hunnu.edu.cn/online/?action=problem&type=show&id=11394&courseid=0

In elementary school, students learn to subtract  fractions by first getting a common
denominator and then subtracting the numerators. However, sometimes a student will
work the problem incorrectly and still arrive at the correct answer. For example, for the
problem
5
4  -
9
12 
one can subtract the numbers in the numerator and then subtract the numbers in the
denominator, simplify and get the answer. i.e.
5
4  −
9
12  =
−4
−8  =
4
8 =
1
2
For a given fraction b/n, your task is to find all of the values a and m, where a≥0 and
m>0, for which
a
m −
b
n =
a−b
m−n
Input
There will be several test cases in the input. Each test case will consist of a single line
with two integers, b and n  (1≤b,n≤106
) separated by a single space. The input will end
with a line with two 0s.
Output
For each case, output all of the requested fractions on a single line, sorted from smallest
to largest. For equivalent fractions, print the  one with the  smaller numerator first.
Output each fraction in the form “a/m” with no spaces immediately before or after the
“/”. Output a single space between fractions.  Output no extra spaces, and do not
separate answers with blank lines.
Sample Input
9 12
12 14
4 12
0 0
Sample Output
0/24 5/20 8/16 8/8 5/4
0/28 9/21 9/7
0/24 3/18 3/6

 

题意:给出b,n,要求满足题意的所有a,m

思路:从样例可以看出,所有m都是从2*n,a是从0开始的,并且得出的两边是对称的,

根据a = (2bmn-b*m*m)/(n*n)我们可以采取枚举m的情况,但是一般枚举肯定超时,但是我们可以通过gcd来优化

 

#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;

__int64 num[1000005][2],len;

__int64 gcd(__int64 n,__int64 m)
{
    if(!m) return n;
    else return gcd(m,n%m);
}

int main()
{
    __int64  n,m,a,b,i,r;
    while(~scanf("%I64d%I64d",&b,&n),b+n)
    {
        printf("0/%I64d",2*n);
        len = 0;
        r = gcd(b,n);
        for(m = 2*n-n/r;m>n;m-=n/r)//枚举优化
        {
            if(m!=n && (2*b*n*m-b*m*m)%(n*n) == 0)//满足公式
            {
                printf(" %I64d/%I64d",(2*b*n*m-b*m*m)/(n*n),m);
                num[len][0] = (2*b*n*m-b*m*m)/(n*n);
                num[len][1] = m;
                len++;
            }
        }
        for(i = len-1;i>=0;i--)//对称
        {
            printf(" %I64d/%I64d",num[i][0],2*n-num[i][1]);
        }
        printf("\n");
    }

    return 0;
}


 

你可能感兴趣的:(水,hunnu)