您的位置:首页 > 其它

NKU两题简单题解析(递归分析与位运算技巧)

2013-08-23 10:41 246 查看
题目:http://acm.nankai.edu.cn/p1002.html



题意:对给定的f(n),当 n>=50025002 的时候,f(n)=n-5;当 n<50025002 的时候,f(n)=f(f(n+2005)),求f(n).



分析:注意本题给出数据n很大-2147483647<n<2147483647,如果你要递归,一是层数太多,会溢出,而是时间不是最优

的,那么在这里,虽然不能直接递归,但是我们还是可以用递归的思想。具体做法就是:



如果n>=50025002,那么我们可以直接计算,如果n<50025002,那么,我们可以先利用f(n)=f(f(n+2005))这个关系把f(n)的计算转化到区间

上去计算,那么我们可以这样看:








其中这里k满足条件:





这样我们就可以直接计算

,我们知道它等于n+2005k-5,那么现在n+2005k-5,就有两种情况:


要么大于等于50025002,要么小于50025002,如果是大于等于,那么直接继续计算,如果是小于,那么,就继续转换。



所以程序我们可以这样写:



void Solve(int n)
{
    int k=1;
    while(k)
    {
        if(n>=50025002)
        {
            n-=5;
            k--;
        }
        else
        {
            n+=2005;
            k++;
        }
    }
    cout<<n<<endl;
}


我感觉这样很好理解,还可以进一步优化的,此处就省略了。



题目:http://acm.nankai.edu.cn/p1021.html



题意:所有3的幂的集合的子集中,输出和为第k大的每个元素值。



分析:对于这个题呢,我感觉最好的做法就是用位运算,我们发现3的幂集合,比如:1,3,9,27,81,.....等等。

有一个特点,那么就是如果我们把输入的k表示为二进制,比如5,就是101,注意二进制从由往左看的话,就代表1,9被选

了,而1+9=10恰好是第5大,所以这样就很简单了,程序可以这样写:

void Solve(LL n)
{
    LL k=0;
    n--;
    while(n)
    {
        if(n&1)
            cout<<(LL)pow(3.0,k*1.0)<<endl;
        n>>=1;
        k++;
    }
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: