• 上两道省选的高精吧!


    T1HAOI2016 放棋子

    题目描述

    给你一个N*N的矩阵,每行有一个障碍,数据保证任意两个障碍不在同一行,任意两个障碍不在同一列,要求你在这个矩阵上放N枚棋子(障碍的位置不能放棋子),要求你放N个棋子也满足每行只有一枚棋子,每列只有一枚棋子的限制,求有多少种方案。

    输入输出格式

    输入格式:

    第一行一个N,接下来一个N*N的矩阵。N<=200,0表示没有障碍,1表示有障碍,输入格式参考样例

    输出格式:

    一个整数,即合法的方案数。

    输入输出样例

    输入样例#1:
    2
    0 1
    1 0
    输出样例#1:
    1


    额,就是递推的错排,证明网上一大坨。。。难打的是高精。。。

    #include<cstdio>
    #include<iostream>
    #include<iomanip>
    #define maxn 5050
    #define mod 10000000000
    #define _ 10
    #define ll long long
    using namespace std;
    struct bignum{
        int sz;
        ll v[maxn];
    }s[3100];
    typedef bignum bg;
    int n;
    
    inline bg operator +(bg a , bg b)
    {
        if(a.sz < b.sz) swap(a,b);
        ll jin = 0;
        for(int i=1;i<=a.sz;i++)
        {
            a.v[i] += b.v[i] + jin;
            jin = a.v[i] / mod;
            a.v[i] %= mod;
        }
        while(jin)
        {
            a.v[++a.sz] = jin % mod;
            jin /= mod;
        }
        return a;
    }
    
    inline bg operator *(bg a , ll b)
    {
        ll jin = 0;
        for(int i=1;i<=a.sz;i++)
        {
            a.v[i] = a.v[i] * b + jin;
            jin = a.v[i] / mod;
            a.v[i] %= mod;
        }
        while(jin)
        {
            a.v[++a.sz] = jin % mod;
            jin /= mod;
        }
        return a;
    }
    
    inline ostream& operator << (ostream &os,bg x)
    {
        ll i;
        os<<x.v[x.sz];
        for(i=x.sz-1;i;i--)
            os<<setfill('0')<<setw(_)<<x.v[i];
        return os;
    }
    
    int main(){
        cin >> n;
        s[1].sz = 1;
        s[1].v[1] = 0;
        s[2].sz = 1;
        s[2].v[1] = 1;    
        for(int i=3;i<=n;i++)
            s[i] = (s[i - 1] + s[i - 2]) * (i - 1);
        cout << s[n];
    }

    T2HNOI2004 高精度开根

    晓华所在的工作组正在编写一套高精度科学计算的软件,一些简单的部分如高精度加减法、乘除法早已写完了,现在就剩下晓华所负责的部分:实数的高精度开m次根。

    因为一个有理数开根之后可能得到一个无理数,所以这项工作是有较大难度的。现在要做的只是这项工作的第一步:只对自然数进行开整数次根,求出它的一个非负根,并且不考虑结果的小数部分,只要求把结果截断取整即可。

    程序需要根据给定的输入,包括需要开根的次数,以及被开根的整数;计算出它的非负根取整后的结果。

    输入输出格式

    输入格式:

    输入文件共有两行,每行都有一个整数,并且输入中没有多余的空格:

    第一行有一个正整数m (1 <= m <= 50),表示要开的根次;

    第二行有一个整数n (0<=n <= 10^10000),表示被开根的数。

    输出格式:

    输出文件只有一行,包括一个数,即为开根取整后的结果。

    输入输出样例

    输入样例#1:
     3
    1000000000
    
    输出样例#1:
    1000


    靠,这个题目网上的奆佬们都用PY,,,,QAQ,,,,不会PY的小蒟蒻难受啊。只有打一波高精了...TAT...
    #pragma GCC optimize(2)
    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<cmath>
    #include<iomanip>
    #define maxn 10050
    #define mod 100000000
    #define _ 8
    #define ll long long
    using namespace std;
    struct bg{
        int sz;
        ll v[maxn];
        bg()
        {
            memset(v,0,sizeof(v));
        }
    };
    
    bg ans;
    int n;
    char shu[100100];
    
    inline ostream& operator << (ostream &os,bg x)
    {
        ll i;
        os<<x.v[x.sz];
        for(i=x.sz-1;i;i--)
            os<<setfill('0')<<setw(_)<<x.v[i];
        return os;
    }
    
    inline bool operator <(bg a , bg b)
    {
        if(a.sz > b.sz) return false;
        if(a.sz < b.sz) return true;
        for(int i=a.sz;i>=0;--i)
        {
            if(a.v[i] < b.v[i]) return true;
            if(a.v[i] > b.v[i]) return false;
        }
        return false;
    }
    
    inline bg operator +(bg a , bg b)
    {
        if(a.sz < b.sz) swap(a , b);
        ll jin = 0;
        for(int i=1;i<=a.sz;++i)
        {
            ll val = a.v[i] + b.v[i] + jin;
            a.v[i] = val % mod;
            jin = val / mod;
        }
        while(jin)
        {
            a.v[++a.sz] = jin % mod;
            jin /= mod;
        }
        return a;
    }
    
    inline bg operator -(bg a , int b)
    {
        for(int i=a.sz;i>1;--i)
        {
            --a.v[i];
            a.v[i-1] += mod;
        }
        a.v[1]--;
        ll jin = 0;
        for(int i=1;i<=a.sz;++i)
        {
            a.v[i] += jin;
            jin = a.v[i] / mod;
            a.v[i] %= mod;
        }
        return a;
    }
    
    inline bg operator *(bg a , bg b)
    {
        bg c;
        for(int i=1;i<=a.sz;++i)
            for(int j=1;j<=b.sz;++j)
                    c.v[i + j - 1] += a.v[i] * b.v[j] ;
        ll ce = a.sz + b.sz - 1,jin = 0;
        for(int i=1;i<=ce;++i)
        {
            c.v[i] += jin;
            jin = c.v[i] / mod;
            c.v[i] %= mod;
        }
        while(jin)
        {
            c.v[++ce] = jin % mod;
            jin /= mod;
        }
        c.sz = ce;
        return c;
    }
    
    inline bg operator /(bg a , int b)
    {
        for(int i=a.sz;i>=1;--i)
        {
            if(a.v[i] & 1) a.v[i - 1] += mod;
            a.v[i] >>= 1;
        }
        a.v[0] = 0;
        if(!a.v[a.sz]) --a.sz;
        return a;
    }
    
    inline bg read()
    {
        bg ans;
        scanf("%s",shu + 1);
        int len = strlen(shu + 1);
        int sq = len;
        int qwer = 0;
        for(int i=1;;++i)
        {
            if(qwer)
            {
                ans.sz = i - 1;
                break;
            }
            for(int j=0;j<_;++j)
            {
                ans.v[i] += (shu[sq--] - '0') * pow(10 , j);
                if(sq < 1)
                {
                    qwer = 1;
                    break;
                }
            }
        }
        return ans;  
    }
    
    inline bg find(bg a)
    {
        bg k;
        k.sz = 1;
        k.v[1] = 1;
        int ce = n;
        while(ce)
        {
            if(ce & 1) k = k * a;
            a = a * a;
            ce >>= 1;
        }
        return k;
    }
    
    int main(){
        cin >> n;
        getchar();
        ans = read();
        
        bg l;
        bg r;
        r.sz = 1;
        r.v[1] = 1;
        
        bg ce;
        ce.sz = 1;
        ce.v[1] = 1;
        
        bg c;
        c.sz = 1;
        c.v[1] = 2;
        
        while(find(r) < ans)
        {
            l = r;
            r = r * c;
        }
        while(l < r)
        {
            bg mid = (l + r) / 2;
            if(find(mid) < ans) l = mid + ce;
            else r = mid;
        }
        
        bg k = l;
        for(int i=1;i<n;++i)
         k = k * l;
        if(ans < k)
            l = l - 1;
        cout << l;
    }

    在BZOJ上是可以轻松跑过的,,,但是洛谷里面被卡了(洛谷里面时限是1.5s,BZOJ5s,程序2.7s)...无语了。。。

  • 相关阅读:
    hadoop中的序列化
    web服务端的架构演变
    网易考拉规则引擎平台架构设计与实践
    spring分布式事务学习笔记(2)
    质量评估面面观--聊一聊软件上线前的质量评估
    用script标签加载
    Windows下命令行下启动ORACLE服务
    笔记本优化八项
    C#编程总结(一)序列化
    学习之路十四:客户端调用WCF服务的几种方法小议
  • 原文地址:https://www.cnblogs.com/kczno1fans/p/7688557.html
Copyright © 2020-2023  润新知