概率,递推,找规律,高精度(FXTZ II,hdu 4043)

总结一下吧。。

像这种题,输入很简单,就几个数,然而正常算运算量很大,或时间复杂度很高,或分类讨论很麻烦的题,就试试找规律吧。只能说很可能是找规律,但也有例外吧。

这题的话,手算或计算机算多几个小数据,要想清楚了别算错了。。找规律就靠它了啊。。如果手算的话,心细一点可能就会发现递推关系式了,化简一下关系式就会变得很简单。没发现的话就把数列写出来,然后加减乘除看看相邻项有没有什么联系啊。。。再不行就看看能不能把Pn表示成Pi(i<n)。。。其实就是在做数学题。。。

以前做过有些题还打表找规律,甚至打表输出的。。。


代码

#include <string>
#include <vector>
#include <algorithm>
#include<iostream>
//#include<cstring>
#include<cstdio>
#include<sstream>
using namespace std;
string mul(string str1,string str2)
{
    vector<int> v_res(str1.size()+str2.size(),0);
    string::size_type i,j;
    vector<int>::size_type k,p;

    reverse(str1.begin(),str1.end());
    reverse(str2.begin(),str2.end());
    for(i = 0; i != str1.size(); ++i)
    {
        for(j = 0; j != str2.size(); ++j)
        {
            v_res[i+j] += (str1[i]-'0') * (str2[j] - '0');
        }
    }
    for(k = 0; k != v_res.size() - 1; ++k)
    {
        v_res[k+1] += v_res[k] / 10;
        v_res[k] = v_res[k] % 10;
    }

    for(p = v_res.size() - 1; p != -1; --p)
    {
        if(v_res[p] != 0) break;
    }
    if(p == -1) p = 0;

    string s_res(p+1,'0');
    for(k = p; k != -1; --k) s_res[p-k] = char(v_res[k] + '0');


    return s_res;

}
string sub(string s1,string s2)
{
    int flag = 0;
    if(s1.length()<s2.length() || (s1.length()==s2.length() && s1 < s2))
    {
        flag = 1;
        string temp=s1;
        s1=s2;
        s2=temp;
    }


    int i,j;
    for(i=s1.length()-1,j=s2.length()-1;i>=0;i--,j--)
    {
        s1[i]=char(s1[i]-(j>=0?s2[j]-'0':0));   //注意细节
        if(s1[i]-'0'<0)
        {
            s1[i]=char(s1[i] + 10);
            s1[i-1]--;
        }
    }

    for(i = 0; i < s1.length(); i++)
    {
        if(s1[i] != '0') break;
    }
    if(i == s1.length()) i = s1.length()-1;
    s1 = s1.substr(i);

    if(flag) s1 = "-" + s1;

    return s1;
}
string sum(string s1,string s2)
{
    if(s1.length()<s2.length())
    {
        string temp=s1;
        s1=s2;
        s2=temp;
    }
    int i,j;
    for(i=s1.length()-1,j=s2.length()-1;i>=0;i--,j--)
    {
        s1[i]=char(s1[i]+(j>=0?s2[j]-'0':0));   //注意细节
        if(s1[i]-'0'>=10)
        {
            s1[i]=char((s1[i]-'0')%10+'0');
            if(i) s1[i-1]++;
            else s1='1'+s1;
        }
    }
    return s1;
}

string div(string s1,string s2)
{
    string res = "0";
    if(s1.length()<s2.length() || (s1.length()==s2.length() && s1 < s2))
    {
        return "0";
    }

    int i;
    int sub_length = s1.length() - s2.length();
    for(i = sub_length; i >= 0; i--)
    {
        string s3(i,'0');
        string s4 = s2 + s3;

        do
        {
            string temp = sub(s1,s4);
            if(temp[0] == '-') break;
            else
            {
                s1 = temp;
                res = sum(res,("1" + s3));
            }
        }while(1);
    }
    return res;
}

string gcd(string a,string b)
{
    return b=="0"?a:gcd(b,sub(a,mul(div(a,b),b)));
}

int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        int n;
        scanf("%d",&n);
        string fz="1";
        string fm="1";
        string s1,s2;
        for(int i=1;i<=n;i++)
        {
            stringstream ss;
            ss<<2*i-1<<" "<<2*i;
            ss>>s1>>s2;
            fz=mul(fz,s1);
            fm=mul(fm,s2);
        }
        string GCD=gcd(fm,fz);
        cout<<div(fz,GCD)<<"/"<<div(fm,GCD)<<endl;
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值