题目:七颗果子(seven.pas/cpp/in/out)
题目描述
作为一位尚未脱团的神牛,即使是美好七夕之夜也不免孤单。这不,他正独自一人躺在树下看着星星,等着苹果砸呢。
青青不是不知道今晚是什么日子,其实他在盘算着,如何才能飞到鹊桥之上,进而……(以下省略10万字)
“嘭”的一声,青青果断被砸中。青青摸着头,正准备抱怨,不想……“嘭嘭嘭嘭嘭嘭”
……(此处省略200字)
果子1:亲,我这里可是有很多钱的喔~
果子2:亲,我这里的钱是果子1的平方喔~
果子3:亲,我知道果子7有多少钱喔~
果子4:亲,我这里的钱是果子1的四方喔~
果子5:亲,我这里的钱是果子1的五方喔~
果子6:亲,我这里的钱是果子1的六方喔~
果子7:亲,你如果能告诉我果子1有多少钱,我就教你飞上天的法术喔~
……(此处省略200字)
经过死缠烂磨,青青终于买通了果子3,知道了果子7手上有多少钱,下面的事情就交给你了~
数据规模
对于前 3 个数据,数字不超过 2^63 - 1。
对于后 7 个数据,数字不超过 10^777。
输入格式
1 行,1 个整数表示果子 7 有多少钱。
输出格式
1 行,1 个整数表示果子 1 有多少钱。
样例输入
16384
样例输出
4
题目描述完全无法理解。。自己试了一下原来就是求七次根号下一个数。
要用高精。一开始我没有压位,结果就只过了3个点,和他们朴素的一样。
关键点有几个。
1、枚举范围太大了。。其实可以缩小。。计算一下可以确定一个上下界。
2、在求7次方的时候,用快速幂,求出平方,四次方,六次方,每次都要判断一下,如果大于n了就返回大于。
3、压位。
1是最重要的,但是实际上2和3结合起来比1效果更好。。
#include <iostream>
using std::cout;
#define MAX(a,b) ((a)>(b)?(a):(b))
const long bit10 = 100000000;
const long bit = 8;
typedef long long ll;
inline void Plus(ll *a,ll *b,ll *c)
{
c[0] = MAX(a[0],b[0]);
for (long i=1;i<c[0]+2;i++)
{
c[i] = 0;
}
for (long i=1;i<c[0]+1;i++)
{
if (i > a[0])
c[i] += b[i];
else if (i > b[0])
c[i] += a[i];
else
c[i] += a[i]+b[i];
if (c[i] >= bit10)
{
c[i+1] += c[i]/bit10;
c[i] %= bit10;
}
}
while (c[c[0]+1])c[0] ++;
while (!c[c[0]] && c[0]>0) c[0] --;
}
inline void Multiply(ll *a,ll *b,ll *c)
{
c[0] = a[0] + b[0];
for (long i=1;i<c[0]+2;i++)
{
c[i] = 0;
}
for (long i=1;i<a[0]+1;i++)
{
for (long j=1;j<b[0]+1;j++)
{
c[i+j-1] += a[i] * b[j];
while (c[i+j-1] >= bit10)
{
c[i+j] += c[i+j-1] / bit10;
c[i+j-1] %= bit10;
}
}
}
while (c[c[0]+1]) c[0]++;
while (!c[c[0]] && c[0]>0) c[0] --;
}
inline void Div2(ll *a,ll *c)
{
for (long i=0;i<a[0]+2;i++)
c[i] = 0;
for (long i=a[0];i>0;i--)
{
c[i-1] += (a[i]&1) * bit10;
c[i] = (c[i] + a[i]) >> 1;
}
c[0] = a[0];
while (!c[c[0]] && c[0]>0) c[0] --;
}
inline void Increase(ll *a,ll *c)
{
// from c[0] to a[0] + 2
c[0] = a[0] + 1;
for (long i=1;i<c[0]+1;i++)
c[i] = a[i];
c[c[0]+1] = c[c[0]+2] = 0;c[1] ++;
for (long i=1;i<c[0]+1;i++)
{
if (c[i] >= bit10)
{
c[i] %= bit10;
c[i+1] /= bit10;
}
else
{
break;
}
}
while (c[c[0]+1]) c[0] ++;
while (!c[c[0]] && c[0]>0) c[0] --;
}
inline void Decrease(ll *a,ll *c)
{
c[0] = a[0] + 1;
for (long i=1;i<c[0]+1;i++)
c[i] = a[i];
c[c[0]+1] = c[c[0]+2] = 0;c[1] --;
for (long i=1;i<c[0]+1;i++)
{
if (c[i] < 0)
{
c[i] += bit10;
c[i+1] --;
}
else
{
break;
}
}
while (!c[c[0]] && c[0]>0) c[0] --;
while (c[c[0]+1]) c[0] ++;
}
inline void output(ll *a)
{
cout << a[a[0]];
for (long i=a[0]-1;i>0;i--)
{
if (a[i] < 10000000)
cout << 0;
if (a[i] < 1000000)
cout << 0;
if (a[i] < 100000)
cout << 0;
if (a[i] < 10000)
cout << 0;
if (a[i] < 1000)
cout << 0;
if (a[i] < 100)
cout << 0;
if (a[i] < 10)
cout << 0;
cout << a[i];
}
}
inline long compare(ll *a,ll *b)
{
if (a[0] != b[0])
return a[0] < b[0]?-1:1;
for (long i=a[0];i>0;i--)
if (a[i] != b[i])
return a[i] < b[i]?-1:1;
return 0;
}
ll tmp[100000];
ll MID[100000];
ll times2[100000];
ll times4[100000];
ll times6[100000];
ll times7[100000];
char num[100000];
ll a[100000];
ll L[100000];
ll R[100000];
inline long calc()
{
Multiply(MID,MID,times2);
if (compare(times2,a) == 1) return 1;
Multiply(times2,times2,times4);
if (compare(times4,a) == 1) return 1;
Multiply(times2,times4,times6);
if (compare(times6,a) == 1) return 1;
Multiply(MID,times6,times7);
return compare(times7,a);
}
int main()
{
freopen("seven.in","r",stdin);
freopen("seven.out","w",stdout);
long _len = 0;
scanf("%s",num+1);
while (num[++_len]){
num[_len]=num[_len]-'0';
}_len--;
for (long i=1;i<_len+1;i++)
{
a[(_len-i)/bit+1] = a[(_len-i)/bit+1]*10+num[i];
}
a[0] = (_len-1)/bit+1;
L[0] = 1;
L[1] = 0;
Decrease(a,R);
while (compare(L,R) < 1)
{
Plus(L,R,tmp);
Div2(tmp,MID);
long rs = calc();
if (rs == -1)
{
Increase(MID,L);
}
else if (rs == 1)
{
Decrease(MID,R);
}
else
{
output(MID);
break;
}
}
return 0;
}