某不知出处的题,前缀和后缀和预处理

Description:

给出数列A1,A2,...,AN,并设

Bi = (A1 * A2 * A3 ... AN) / Ai mod (109 + 7)

现要求把所有的Bi 算出来

Input:

输入包含多组测试数据。对于每组数据,第1 行,1 个整数N(1 ≤N ≤100,000), 表示数列的长度。第2

行,N 个整数A1,A2,...,AN(1 ≤Ai≤109),表示给出的数列。输入以一个 0 表示结尾。

Output:

对于每组数据,输出一行,N 个整数用空格分隔,表示算出的B1,B2,...,BN。

Sample Input:

3

1 2 3

0

Sample Output:

6

3

2

    题意:说的很详细了里面。我找不到原题。。。好多博主写过这个,但是都没有贴地址,所以我也没发帖,见谅哈。

    解析:看数据,ai过大,直接乘就溢出了。使用(a*b)%c==(a%c*b%c)%c。我们可以直接这么处理,乘起来。但问题是,对于乘法,有模分配律,但是除法没有。那么问题来了,对于题意来讲,bi=(a1*a2....*an)/ai mod,来讲,直接乘的时候不算ai,约掉不就好了?不行,因为n的数据,n*n不行。所以引入前缀积和后缀积来处理。举个例子,b2=(a1*a2*a3*a4)/a2  %mod。。

       原式就是b2=(a1*a3*a4)%mod==(a1%mod*(a3*a4)%mod)%mod。这里的a1,是i=2往前的前缀积,a3*a4是i=2之后的后缀积。那么显而易见,前缀和与后缀和在这里面处理的很巧妙。

#include<iostream>
#include<vector>
#include<set>
#include<cmath>
using namespace std;    
typedef long long ll;
const int maxn=1e5+10;
const int mod=1000000007;
ll a[maxn],l[maxn],r[maxn];
int main()
{
    int n;
    while(scanf("%d",&n)&&n)
    {
        for(int i=1;i<=n;i++)
        {
            scanf("%lld",&a[i]);
        }
        l[0]=1;
        r[n+1]=1;
        for(int i=1;i<=n;i++)
            l[i]=(a[i]*l[i-1])%mod;
        for(int i=n;i>=1;i--)
            r[i]=(a[i]*r[i+1])%mod;
        for(int i=1;i<=n;i++)
        {
            printf("%lld\n",(l[i-1]*r[i+1])%mod);
        }
    }
}

猜你喜欢

转载自www.cnblogs.com/liyexin/p/12517952.html