POJ - 2109 Power of Cryptography(高精度log+二分)

Current work in cryptography involves (among other things) large prime numbers and computing powers of numbers among these primes. Work in this area has resulted in the practical use of results from number theory and other branches of mathematics once considered to be only of theoretical interest. 
This problem involves the efficient computation of integer roots of numbers. 
Given an integer n>=1 and an integer p>= 1 you have to write a program that determines the n th positive root of p. In this problem, given such integers n and p, p will always be of the form k to the n th. power, for an integer k (this integer is what your program must find).


Input

The input consists of a sequence of integer pairs n and p with each integer on a line by itself. For all such pairs 1<=n<= 200, 1<=p<10 101 and there exists an integer k, 1<=k<=10 9 such that k n = p.


Output

For each integer pair n and p the value k should be printed, i.e., the number k such that k n =p.


Sample Input

2 16
3 27
7 4357186184021382204544

Sample Output

4
3
1234题意:给出n和p(n<=200,p<=10^101),求方程k^n=p的k的正整数解,保证k<=10^9

题解:这道神题传说有非常神奇的解f♂a

   然而并没有什么卵用,你只会收到一连串的WA

   该题的意图应该是贪心,至于怎么贪……わかない……

好吧,我太菜了,只能用最暴力的方法,设x^y=p对于y>n的解来说,x必然小于k对于y<n的解来说,x必然大于k对于x来说单调性所以可以二分至于y该怎么求……想必一个高精度的log就行了!而且只需要保留个位即可感觉我的代码还是有问题的,但莫名1A了代码如下
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;

struct big
{
    int len;
    int num[200];
};

int n;

void trans(char* a,big &b)
{
    memset(b.num,0,sizeof(b.num));
    int len=strlen(a);
    for(int i=0; i<len; i++)
    {
        b.num[len-i-1]=a[i]-‘0‘;
    }
    b.len=len;
}

void trans_(int a,big &b)
{
    memset(b.num,0,sizeof(b.num));
    int len=0;
    while(a)
    {
        b.num[len++]=a%10;
        a/=10;
    }
    b.len=len;
}

void print(big a)
{
    for(int i=a.len-1; i>=0; i--)
    {
        printf("%d",a.num[i]);
    }
    puts("");
}

int comp(big x,big y)
{
    if(x.len>y.len)
    {
        return 1;
    }
    if(x.len<y.len)
    {
        return -1;
    }
    for(int i=x.len-1; i>=0; i--)
    {
        if(x.num[i]>y.num[i])
        {
            return 1;
        }
        if(x.num[i]<y.num[i])
        {
            return -1;
        }
    }
    return 0;
}

big sub(big a,big b)
{
    big c;
    int len=a.len;
    int lenc=len;
    for(int i=0; i<len; i++)
    {
        c.num[i]=a.num[i]-b.num[i];
        if(c.num[i]<0)
        {
            c.num[i]+=10;
            a.num[i+1]--;
        }
    }
    while(c.num[lenc-1]==0&&lenc>1)
    {
        lenc--;
    }
    c.len=lenc;
    return c;
}

void mul_ten(big &x)
{
    int len=x.len;
    len++;
    for(int i=len-1; i>=0; i--)
    {
        x.num[i+1]=x.num[i];
    }
    x.num[0]=0;
    while(x.num[len-1]==0&&len>1)
    {
        len--;
    }
    x.len=len;
}

big div(big x,big y)
{
    big f,m;
    memset(f.num,0,sizeof(f.num));
    memset(m.num,0,sizeof(m.num));
    m.len=1;
    int len=x.len;
    for(int i=x.len-1; i>=0; i--)
    {
        mul_ten(m);
        m.num[0]=x.num[i];
        while(comp(m,y)!=-1)
        {
            m=sub(m,y);
            f.num[i]++;
        }
    }
    while(f.num[len-1]==0&&len>1)
    {
        len--;
    }
    f.len=len;
    return f;
}

int check(big x,big y)
{
    big z;
    int cnt=0;
    z.len=1;
    z.num[0]=1;
    while(!comp(x,z)==0)
    {
        if(comp(x,y)==-1)
        {
            break;
        }
        cnt++;
        x=div(x,y);
    }
    if(cnt<n)
    {
        return 0;
    }
    else
    {
        return 1;
    }
}

int main()
{
    char b[202];
    int a;
    big x,y;
    while(scanf("%d %s",&n,b)==2)
    {
        memset(x.num,0,sizeof(x.num));
        memset(y.num,0,sizeof(y.num));
        int l=2,r=1000000000;
        int mid;
        trans(b,y);
        while(l<r)
        {
            mid=(l+r)>>1;
            trans_(mid,x);
            int flag=check(y,x);
            if(flag)
            {
                l=mid;
            }
            else
            {
                r=mid-1;
            }
            if(r-l<=1)
            {
                trans_(r,x);
                if(check(y,x))
                {
                    printf("%d\n",r);
                    break;
                }
                else
                {
                    printf("%d\n",l);
                    break;
                }
            }
        }
    }
}

 

原文地址:https://www.cnblogs.com/stxy-ferryman/p/8430947.html

时间: 2024-10-08 01:29:50

POJ - 2109 Power of Cryptography(高精度log+二分)的相关文章

POJ - 2109 - Power of Cryptography = 高精度整数

http://poj.org/problem?id=2109 给一个大概100位的高精度整数p,找他的n次方根,貌似题目有问题,不一定会有开根开得尽的情况,这个时候要找的就是最大的根. 那这样有什么意思呢? 这种题按道理要用Java去写的,可以先从p和n的关系找到根的位数,然后在这个范围里面二分会更快. 具体来说,比如22位的p,7次方根,就是22/7的上整,取4位数. 还有就是因为题目的原因,double的精度对100位的高精度整数开根是足够的,也就是不会的话可以试试莽一发long doubl

POJ 2109 Power of Cryptography

http://poj.org/problem?id=2109 题意: 给出两个数n和p,要求p是n的几次方. 思路: 好神奇的题目,我一开始想那就一直除呗,后来又想到了有pow这种公式,居然这么简短就过了,有点不可思议. 1 #include<iostream> 2 #include<cmath> 3 using namespace std; 4 5 int main() 6 { 7 double n, p; 8 while (cin >> n >> p)

Poj 2109 / OpenJudge 2109 Power of Cryptography

1.Link: http://poj.org/problem?id=2109 http://bailian.openjudge.cn/practice/2109/ 2.Content: Power of Cryptography Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 18872   Accepted: 9520 Description Current work in cryptography involves (

POJ 3233-Matrix Power Series(矩阵快速幂+二分求矩阵和)

Matrix Power Series Time Limit:3000MS     Memory Limit:131072KB     64bit IO Format:%I64d & %I64u Submit Status Practice POJ 3233 Appoint description:  System Crawler  (2015-02-28) Description Given a n × n matrix A and a positive integer k, find the

POJ 2019 Power of Cryptography

技巧. #include<iostream> #include<cmath> using namespace std; double n,p; int main(){ while(cin>>n>>p){ cout<<pow(p,1/n)<<endl; } }

POJ 2109 :Power of Cryptography

Power of Cryptography Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 18258   Accepted: 9208 Description Current work in cryptography involves (among other things) large prime numbers and computing powers of numbers among these primes. W

POJ 3233 - Matrix Power Series ( 矩阵快速幂 + 二分)

POJ 3233 - Matrix Power Series ( 矩阵快速幂 + 二分) #include <cstdio> #include <cstring> #include <algorithm> using namespace std; typedef long long LL; #define MAX_SIZE 30 #define CLR( a, b ) memset( a, b, sizeof(a) ) int MOD = 0; int n, k; st

POJ_2109 Power of Cryptography 数学

题目链接:http://poj.org/problem?id=2109 参考链接:http://blog.csdn.net/synapse7/article/details/11672691 乍一看似乎高精度,但是double足矣.....15位有效数字, 指数范围-307~308(10位基数) 代码: 1 int main(){ 2 double n, p; 3 while(scanf("%lf %lf", &n, &p) == 2){ 4 double k = po

poj2109 Power of Cryptography(数学题)

题目链接:http://poj.org/problem?id=2109 Description Current work in cryptography involves (among other things) large prime numbers and computing powers of numbers among these primes. Work in this area has resulted in the practical use of results from num