Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/138.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ c+中俄罗斯农民算法的整数溢出+;_C++_Algorithm_Integer Overflow - Fatal编程技术网

C++ c+中俄罗斯农民算法的整数溢出+;

C++ c+中俄罗斯农民算法的整数溢出+;,c++,algorithm,integer-overflow,C++,Algorithm,Integer Overflow,我遇到了一个俄罗斯农民指数法(RPE)的问题,该方法计算指数的速度比传统方法计算x的n次方快得多。 常规方法 int power(int base, int exponent) { int result = 1; for(register int i = 1; i <= exponent; i++) { result *= base; } return result; } 问题说明输入由定义查询数量的整数q组成。每个查询由4个数字组成,用空

我遇到了一个俄罗斯农民指数法(RPE)的问题,该方法计算指数的速度比传统方法计算x的n次方快得多。

常规方法

int power(int base, int exponent) {
    int result = 1;
    for(register int i = 1; i <= exponent; i++) {
        result *= base;
    }
    return result;
}
问题说明输入由定义查询数量的整数
q
组成。每个查询由4个数字组成,用空格
a、b、k、m
分隔。对于每个查询,我必须找到
z=(a+ib)^k
,因为
re(z)
im(z)
的值可能非常大,所以我必须打印
re(z)mod m
im(z)mod m

问题发生在的测试用例中
8 2 10 1000000000
其中预期输出为
880332800 927506432
,我的输出为
-119667200-72493568
您需要更换

((ar*br)%m-(ai*bi)%m)%m

((ar*br)%m+m-(ai*bi)%m)%m

由于上述表达式的结果可能是负值,因此需要替换

((ar*br)%m-(ai*bi)%m)%m

((ar*br)%m+m-(ai*bi)%m)%m


因为你可以从上面的表达式中得到一个负值,这是一个非常简洁的算法,我最后写了自己的算法

我不认为在计算过程中减少中间结果会如何使数学工作,恰恰相反

不过,使用复杂的方法是可行的

我计划将此算法添加到我的工具箱中,因此它与您的实现略有不同。我使用了论文的算法,它减少了1次乘法运算。处理负数模的方法在main()中

#包括
#包括
模板
T fastExp(tx,无符号整数e)
{
如果(e==0)
返回T(1);
而(!(e&1))
{
x*=x;
e>>=1;
}
自动y=x;
e>>=1;
while(e)
{
x*=x;
国际单项体育联合会(e&1)
y*=x;
e>>=1;
}
返回y;
}
int main()
{
std::配合物x{8,2};
自动y=fastExp(x,10);
长k=1000000000LL;
std::复z;
y-={floor(y.real()/k),floor(y.imag()/k)};
复数r{(long-long)y.real(),(long-long)y.imag()};
while(r.real()<0)
r、 _Val[0]+=k;
while(r.imag()<0)
r、 _Val[1]+=k;

std::cout这是一个如此简洁的算法,我最终编写了自己的算法

我不认为在计算过程中减少中间结果会如何使数学工作,恰恰相反

不过,使用复杂的方法是可行的

我计划将此算法添加到我的工具箱中,因此它与您的实现有点不同。我使用了论文中的算法,它可以减少1次乘法。处理负数模的方法在main()中

#包括
#包括
模板
T fastExp(tx,无符号整数e)
{
如果(e==0)
返回T(1);
而(!(e&1))
{
x*=x;
e>>=1;
}
自动y=x;
e>>=1;
while(e)
{
x*=x;
国际单项体育联合会(e&1)
y*=x;
e>>=1;
}
返回y;
}
int main()
{
std::配合物x{8,2};
自动y=fastExp(x,10);
长k=1000000000LL;
std::复z;
y-={floor(y.real()/k),floor(y.imag()/k)};
复数r{(long-long)y.real(),(long-long)y.imag()};
while(r.real()<0)
r、 _Val[0]+=k;
while(r.imag()<0)
r、 _Val[1]+=k;

std::cout什么是奇怪的答案?展示一些预期输出/要添加到gdelab建议中的输出的示例。如果您为此编写一个测试工具,它可能会很好地为您服务。请花一些时间阅读。为了帮助您进行调试,请尝试将大表达式分解为小表达式,以便更容易地查看intermediate results.你对代码进行了过度设计。这不应该是一个类。读取输入是一个与求幂运算完全无关的问题。你使用复数的理由我也不清楚:它们不会让溢出神奇地消失。使用调试器!奇怪的答案是什么?显示一些示例预期输出/您要添加到gdelab建议的内容中的输出如果您为此编写一个测试工具,可能会对您很有帮助。请花一些时间阅读。为了帮助您进行调试,请尝试将大型表达式分解为小型表达式,以便更容易看到中间结果。您对代码的设计过于复杂。这说明uld不是一个类。读取输入是一个与求幂完全无关的问题。我也不清楚你使用复数的理由:它们不会神奇地消除溢出。使用调试器!@MichaëlRoy,但为什么?表达式if
(ar*br)的末尾有
%m
%m>=0
然后
((ar*br)%m+m>=m
这是不对的。无论如何,在计算x**y时使用中间值的任意模在数学上是不合理的。@MichaëlRoy,这没关系,因为在最后我们得到了除以
m
@MichaëlRoy的余数,但是为什么呢?表达式if
的末尾有
%m
(ar*br)%m>=0
然后
((ar*br)%m+m>=m
这是不对的。无论如何,在计算x**y时使用中间值的任意模在数学上是不合理的。@MichaëlRoy,这没关系,因为最后我们得到了被
m
除的余数。
#include<iostream>
#include<complex>
using namespace std;

class Solution {
    int m;
    long long int k;
    complex<long long int> num;
    complex<long long int> russianPeasantExponentiation(), multiply(complex<long long int>, complex<long long int>);
public:
    void takeInput(), solve();
};

void Solution::takeInput() {
    int a, b;
    cin >> a >> b >> k >> m;
    num = complex<long long int> (a, b);
}

void Solution::solve() {
    complex<long long int> res = russianPeasantExponentiation();
    cout << real(res) << " " << imag(res) << endl;
}

complex<long long int> Solution::russianPeasantExponentiation() {
    complex<long long int> temp1(1, 0), temp2 = num;
    while(k) {
        if(k % 2) {
            temp1 = multiply(temp1, temp2);
        }
        temp2 = multiply(temp2, temp2);
        k /= 2;
    }
    return temp1;
}

complex<long long int> Solution::multiply(complex<long long int> a, complex<long long int> b) {
    long long int ar = real(a), ai = imag(a), br = real(b), bi = imag(b);
    complex<long long int> result(((ar * br) % m - (ai * bi) % m) % m, ((ar * bi)%m + (ai * br)%m)%m);
    return result;
}

int main() {
    int q;
    cin >> q;
    while(q--) {
        Solution obj;
        obj.takeInput();
        obj.solve();
    }
    return 0;
}
#include <complex>
#include <iostream>

template <typename T>
T fastExp(T x, unsigned int e)
{
    if (e == 0)
        return T(1);

    while (!(e & 1))
    {
        x *= x;
        e >>= 1;
    }

    auto y = x;
    e >>= 1;
    while (e)
    {
        x *= x;
        if (e & 1)
            y *= x;
        e >>= 1;
    }
    return y;
}


int main()
{
    std::complex<double> x{ 8, 2 };

    auto y = fastExp(x, 10);

    long long k = 1000000000LL;

    std::complex<double> z;
    y -= { floor(y.real() / k), floor(y.imag() / k) };

    std::complex<long long> r{ (long long)y.real(), (long long)y.imag() };
    while (r.real() < 0)
        r._Val[0] += k;

    while (r.imag() < 0)
        r._Val[1] += k;

    std::cout << "result: " << r.real() << " + " << r.imag() << " i" << "\n";
}