vijos P1375 大整数(高精不熟的一定要做!)

/*
我尼玛这题不想说啥了
亏了高精写的熟.....
加减乘除max都写了
高精二分
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#define maxn 1010
#define memcpy(a,b); for(int i=0;i<=1000;i++)a[i]=b[i];
using namespace std;
int n[maxn],len,l[maxn],r[maxn],mid[maxn],ans[maxn];
char s[maxn];
void Plus(int a[maxn],int b[maxn]){
    int L=max(a[0],b[0]);
    int c[maxn];memset(c,0,sizeof(c));
    for(int i=1;i<=L;i++)
        c[i]=a[i]+b[i];
    for(int i=1;i<=L;i++)
        if(c[i]>9){c[i+1]++;c[i]%=10;}
    if(c[L+1])L++;c[0]=L;
    memcpy(a,c);
}
void Sub(int a[maxn]){
    a[1]--;
    int p=1;
    while(a[p]<0){
        a[p]=9;p++;a[p]--;
    }
    if(a[a[0]]==0)a[0]--;
}
void Mul(int a[maxn],int b[maxn]){
    int c[maxn];memset(c,0,sizeof(c));
    int l1=a[0],l2=b[0],l3=l1+l2;
    for(int i=1;i<=l1;i++){
          int x=0;
          for(int j=1;j<=l2;j++){
              c[j+i-1]+=a[i]*b[j]+x;
            x=c[i+j-1]/10;
            c[i+j-1]=c[i+j-1]%10;
        }
        c[i+l2]=x;
    }
    int k=0;
    for(int i=l3;i>=0;i--)
        if(c[i]){k=i;break;}
    c[0]=k;memcpy(a,c);
}
void Div(int a[maxn],int x){
    int b[maxn],c=0;memset(b,0,sizeof(b));
    for(int i=a[0];i>=1;i--){
        b[i]=(c*10+a[i])/x;c=a[i]%x;
    }
    int k=0;
    for(int i=a[0];i>=0;i--)
        if(b[i]){k=i;break;}
    b[0]=k;memcpy(a,b);
}
bool Cmp(int a[maxn],int b[maxn]){
    if(a[0]<b[0])return 1;
    else if(a[0]>b[0])return 0;
    for(int i=a[0];i>=1;i--){
        if(a[i]<b[i])return 1;
        if(a[i]>b[i])return 0;
    }
    return 1;
}
void Cal(int x[maxn]){
    int a[maxn],b[maxn],c[maxn],d[maxn],e[maxn];
    e[0]=1;e[1]=3;memset(a,0,sizeof(a));
    memcpy(b,x);memcpy(c,x);memcpy(d,x);
    Mul(b,x);Mul(b,x);Mul(c,x);Mul(d,e);
    Plus(a,b);Plus(a,c);Plus(a,d);
    memcpy(x,a);
}
bool Judge(int a[maxn]){
    int b[maxn];memcpy(b,a);
    Cal(b);
    return Cmp(b,n);
}
void cal(int a[maxn]){
    int b[maxn],c[maxn];
    memcpy(b,l);memcpy(c,r);
    Plus(b,c);Div(b,2);
    memcpy(a,b);
}
int main()
{
    scanf("%s",s);
    len=strlen(s);
    for(int i=1;i<=len;i++)
        n[i]=s[len-i]-‘0‘;
    n[0]=len;
    l[0]=1;r[0]=50;
    for(int i=1;i<=50;i++)r[i]=1;
    while(Cmp(l,r)){
        cal(mid);int a[maxn];
        memset(a,0,sizeof(a));
        a[0]=1;a[1]=1;
        if(Judge(mid)){
            memcpy(l,mid);
            Plus(l,a);
            memcpy(ans,mid);
        }
        else{
            memcpy(r,mid);
            Sub(r);
        }
    }
    for(int i=max(ans[0],1);i>=1;i--)
        printf("%d",ans[i]);
    return 0;
}
时间: 2024-10-09 17:34:26

vijos P1375 大整数(高精不熟的一定要做!)的相关文章

VIjos 大整数(超级恶心的高精)

背景 很久很久以前,有个整数很大很囧 描述 一个k(1<=k<=80)位的十进制正整数N,就是所谓的大整数.请你设计程序,对于给出的某一个大整数N,找到满足p^3+p^2+3p<=n的p的最大值. 格式 输入格式 输入数据只有一行,是一个K位的大整数N,行首行未无多余空格 输出格式 输出第一行为你所找到的P最大值,行首行末别乱加东西 样例1 样例输入1 1000000000000001000000000000003000000000000001 Copy 样例输出1 1000000000

codevs 3119 高精度练习之大整数开根 (各种高精+压位)

/* codevs 3119 高精度练习之大整数开根 (各种高精+压位) 二分答案 然后高精判重 打了一个多小时..... 最后还超时了...压位就好了 测试点#1.in 结果:AC 内存使用量: 256kB 时间使用量: 0ms 测试点#2.in 结果:AC 内存使用量: 256kB 时间使用量: 1ms 测试点#3.in 结果:AC 内存使用量: 256kB 时间使用量: 0ms 测试点#4.in 结果:AC 内存使用量: 256kB 时间使用量: 10ms 测试点#5.in 结果:AC 内

大整数因子(高精mod)

大整数的因子 总时间限制:  1000ms 内存限制:  65536kB 描述 已知正整数k满足2<=k<=9,现给出长度最大为30位的十进制非负整数c,求所有能整除c的k. 输入 一个非负整数c,c的位数<=30. 输出 若存在满足 c%k == 0 的k,从小到大输出所有这样的k,相邻两个数之间用单个空格隔开:若没有这样的k,则输出"none". 样例输入 30 样例输出 2 3 5 6 代码 高精模运算 #include<iostream> #inc

高精阶乘

求n!.当n很大的时候,会超出整数的范围. 这里用数组来进行高精阶乘.a[1]是个位,a[2]是十位......依次类推.每次要乘一个数的时候,就从个位(即a[1])开始乘这个数,>10的时候要%10再进位. 1 #include<cstdio> 2 #include<cstring> 3 const int N=100000; 4 5 int a[N]; 6 int i, j, n; 7 int t, pos/*位数*/, carry/*进位*/; 8 9 int main

大整数算法[13] 单数位乘法

★ 引子 最近在折腾 wxWidgets,同时拖延症又犯了,所以中断了好久.这次来讲讲单数位乘法,前面讲到 Comba 和 Karatsuba 乘法,这两个算法适合用来处理比较大的整数,但是对于一个大整数和一个单精度数相乘,其效果反而会不好,因为计算量过多.实际上单数位乘法只是基线乘法的一个特例,不存在嵌套循环进位,因此可以通过优化减少计算量.另外与完整的乘法不同的是,单数位乘法不需要什么临时变量存储和内存分配(目标精度增加除外). ★ 算法思路         单数位乘法类似于计算 12345

HDOJ1002-A + B Problem II(高精加)

Problem Description I have a very simple problem for you. Given two integers A and B, your job is to calculate the Sum of A + B. Input The first line of the input contains an integer T(1<=T<=20) which means the number of test cases. Then T lines fol

【日常学习】【区间DP+高精】codevs1166 矩阵取数游戏题解

题目来自NOIP2007TG3 如果在考场上我现在已经歇菜了吧 今天一整天的时间全部投在这道题上,收获不小. 先上题目 题目描述 Description [问题描述] 帅帅经常跟同学玩一个矩阵取数游戏:对于一个给定的n*m 的矩阵,矩阵中的每个元素aij均 为非负整数.游戏规则如下: 1. 每次取数时须从每行各取走一个元素,共n个.m次后取完矩阵所有元素: 2. 每次取走的各个元素只能是该元素所在行的行首或行尾: 3. 每次取数都有一个得分值,为每行取数的得分之和,每行取数的得分= 被取走的元素

高精除~~~

终于到高精除啦!!! 太令人开心了,我准备将高精除分为两个部分来讲 因为高精除中有高精除低精还有高精除高精 所以啊,这个先将高精除低精展现给大家 首先 因为是大整数除以小整数,所以我们运用的是按位相除法 做除法时,每一次的商都在0~9之内,每次求得的余数连接以后的若干位得到的新数被继续做除法. 因此在高精除法中还会涉及乘法和减法运算并且伴有移位处理. 为了简洁,运用0~9次循环减法取代商值. 好像可以直接上代码, 这个我找不到例题真是抱歉 #include<cstdio> #include&l

【模板】高精算法

利用计算机进行数值计算,有时会遇到这样的问题:有些计算要求精度高,希望计算的数的位数可达几十位甚至几百位,虽然计算机的计算精度也算较高了,但因受到硬件的限制,往往达不到实际问题所要求的精度.我们可以利用程序设计的方法去实现这样的高精度计算.介绍常用的几种高精度计算的方法. 高精度计算中需要处理好以下几个问题: 1)数据的接收方法和存贮方法 数据的接收和存贮:当输入的数很长时,可采用字符串方式输入,这样可输入数字很长的数,利用字符串函数和操作运算,将每一位数取出,存入数组中.另一种方法是直接用循环