上两道省选的高精吧!

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)...无语了。。。

posted @ 2017-10-18 20:06  cc123321  阅读(221)  评论(0编辑  收藏  举报