如果通过循环求和,下面的程序会找到正确的答案,但如果通过GP的公式求和,则会找到不正确的答案.为什么

The following program finds the correct answer if summation is done via loop but incorrect if done via formula for GP. Why?

本文关键字:答案 如果 求和 为什么 不正确 GP 程序 循环      更新时间:2023-10-16

以下代码是我对该问题的解决方案:http://codeforces.com/contest/327/problem/C

我通过循环执行求和的第一部分(因此时间复杂度较差)给出了正确的答案。

我使用几何级数公式的第二部分在许多测试用例中返回了错误的答案,尽管我认为使用的公式是正确的。

我做错了什么?(编辑:-发现问题。在最后解释)

#include<stdio.h>
#include<string>
#include<vector>
#include<iostream>
typedef long long int lli;
using namespace std;
lli power(lli base, lli exponent)
{
    lli result=1;
    while(exponent)
    {
        if(exponent & 1)
            result=(result*base)%1000000007;
        exponent>>=1;
        base=(base*base)%1000000007;
    }
    return result%1000000007;
}
int main()
{
    string n;
    cin>>n;
    lli k;
    cin>>k;
    vector<int> position;
    for(int i=0;i<n.length();i++)
        if(n[i]=='5' || n[i]=='0')
            position.push_back(i);
    lli m=0;
    for(int i=0;i<position.size();i++)
        m=(m+power(2,position[i]))%1000000007;
    lli answer=0;
    lli l=n.length();
// part1
// the following is finding summation via loop
    for(int i=1;i<=k;i++)
        answer=(answer + (power(2,l*(k-i))*m)%1000000007)%1000000007;
    cout<<answer<<endl;
//part2
// the following finds the sum by using gp formula (1st_term*(ratio^no_of_terms-1)/(ratio-1))    
    answer=1;
    answer=((power(power(2,l),k) - 1)/(power(2,l)-1))%1000000007;
    answer*=m%1000000007;
    cout<<answer<<endl;
    return 0;
}

样本输入和输出耦合

输入1:

45550003

输出1:

20806382080638

输入2:

45550008

输出2:

907276560529323732

编辑:-我已经解决了问题。未定义除法上的模。幂函数返回幂模K,其中K=1000000007。让我们把这个新值称为减少值。我正在划分两个减少的值。因此,最终答案也比实际答案要少。既然我已经发现了他的问题,我仍然不知道如何克服这个问题。

第二版:-将第二部分改为以下作品(在线找到)。我不知道为什么。

answer=(power(power(2,l),k) - 1);
answer=(answer*power((power(2,l)-1),K-2))%K;
answer=(answer*m)%K;

有趣;谢谢你的问题和张贴修复。fyi,这是对你正在做的事情的解释:

你可能会看到,你已经用乘以x^(K-2)代替了除以x(即乘以1/x)。所以问题是:为什么是K-2?

答案基本上是费马的小定理,它说当你对素数K(100000007是素数)进行乘法运算时,x^(K-1)=1。如果你把它的两边除以x,那么你得到x^(K-2)=1/x。

我希望你能看到这是如何解释你的代码为什么工作的——一方面你有你的K-2,另一方面除以x,所以K-2的幂等于取倒数。

例如,考虑取模5(它是素数)并将9除以3。

9/3=3和3%5=3,这是我们想要的,但分割可能是一个问题:

(9%5)/3=4/3=?这意味着模5是什么?(这是你的错误)

所以让我们使用K-2技巧:9*(3^(5-2))=9*(3^3)=9*27=243和243%5=3

或者,(9%5)*(3^(5-2))=4*(3^3)=4*27=108和108%5=3

long long int表达式中,您需要确保您的文字常量也是long long int(目前您使用int作为文字常量)。因此,例如更改:

    base=(base*base)%1000000007;

至:

    base=(base*base)%1000000007LL;

更好的是,您不应该在代码中乱丢硬编码的常量,而是只定义一个常量并使用它,例如

const long long int K = 1000000007LL;
....
base=(base*base)%K;

模运算符%先于*=运算符

相关文章: