2014_csu选拔1_B

Description

  Here is no naked girl nor naked runners, but a naked problem: you are to find the K-th smallest element in the set of all irreducible fractions , with 0<p<q≤N.

Input

  The first line of input is an integer T(T≤1000), indicated there are T cases in the file.
For each cases, there is one line with two positive integers N and K.(1≤K<N≤1000000)

Output

  For each case, output a line containing answer.

Sample Input

4
5 1
5 2
5 3
5 4

Sample Output

1/5
1/4
1/3
2/5


昨天陶叔告诉我直接暴力DFS,我当时推出个规律是,最小的一定是 1/n,然后1/n和2/n中间隔着一些分母比n小的分数,我一开始觉得这些分数就是1/(n-1)..(n-i),照此规律,前几个数是可以满足的,后来发现错了,i/n和i+1/n之间隔的分数不可能就是这样能枚举出来,还有一些分子比i大的同样可以存在于里面,所以这个DFS宣告失败。
后来看了下别人代码,发现有个规律就是 1/(n)一定比1/(n-1)小,而 2/(n)一定是比 1/(n-1)大,所以通过这个构建子树,从 1/2开始先向左扩张,找到最小的(即 1/n),然后回退找到父亲那里就是次小的,然后搜右子树,。。其实就是个中序遍历就可以了。
发现写完后,给个符合题目要求的比较大的数据程序直接崩了,我cout了一下,发现是dfs栈开不了那么多,但是在OJ上是可以成功运行的,所以有时候本机会崩的程序好像OJ不一定会崩,别看到大数据本机运行崩了就以为通不过OJ
#include <iostream>
#include <cstdio>
using namespace std;
int n,k;
struct node
{
    int p,q;
    node operator+(const node &rhs)
    {
        node nt;
        nt.p=p+rhs.p;
        nt.q=q+rhs.q;
        return nt;
    }
};
node ans;
bool dfs(node f1,node f2)
{
    if (k==0) return 1;
    node nf=f1+f2;
    if (nf.q>n) return false;//边界设置
    //cout<<nf.q<<" "<<n<<endl;
    bool flag=dfs(f1,nf);
    //cout<<nf.q<<endl;
    if (flag) return 1;
    if (!flag)
    {
        k--;//搜到边界就说明该数肯定为接下来要找的这个次序的值
        if (k==0){
            ans=nf;
            return 1;
        }
    }
    return dfs(nf,f2);
}
int main()
{
    //std::ios::sync_with_stdio(false);
    //freopen("naked.in","r",stdin);
    //freopen("csu_b.out","w",stdout);
    int t;
    scanf("%d",&t);
    while (t--)
    {
        scanf("%d%d",&n,&k);
        node f=(node){0,1}; //通过f和nf控制向左子树和右子树走
        node nf=(node){1,1};
        //cout<<" pass"<<endl;
        dfs(f,nf);
        printf("%d/%d\n",ans.p,ans.q);
    }
    return 0;
}

我发现自己代码规范写的真差,今天铁哥也讲了这个,确实要改进

posted @ 2014-03-27 17:45  KRisen  阅读(231)  评论(0编辑  收藏  举报