Problem C. Kickstart Alarm Google Kickstart Round C 2018

这一题把公式拆开是可以找到规律的。我开始找出了固定i-th exponential-power,得到一个很冗长的公式,再对i求和。然而大数据并不能算出来。。

另一个角度是针对每个A[i],观察其贡献的值、

对于数组[a,b,c,d,e],a作为sub array的第一个元素总计5次,b作为sub array的第一个元素总计4次,c作为sub array的第一个元素总计3次,对应的贡献是A[i]*(1^1+1^2+...+1^K)

b作为sub array的第2个元素总计4次,c作为sub array的第一个元素总计3次,…对应的贡献是A[i]*(2^1+2^2+...+2^K)

由此可以得出,A[i]的贡献是

A[i]*(N-i+1)*(geo_sum(i,K)+geo_sum(2,K)+...+geo_sum(i,K)), geo_sum(x,K)=x+x^2+x^3+...+x^K

最终结果对所有的A[i]求和即可。

等比数列a1,a2,..an, an=a1*q^(n-1)求和Sn=(a1*(1-q^n))/(1-q)=x(x^K-1)/(x-1)。除法不能直接mod,需要先算出逆序数,i.e., if P is prime, (1/a)%P=a^(P-2)。

另外取模的时候有很多坑。。

1. 如果用(x^(K+1)%mod-x)*inv[x-1]%mod,x^(K+1)%mod-x是有可能<0的,所以要判断中间结果是否<0,如果<0就先+mod再乘后面的数。

2. 对于a*b*c % mod这样的连乘,一定要在每一个相乘的项后面取mod,否则很可能中途就overflow了。比如我开始写成了((a%mod)*(b%mod)*(c%mod))%mod就一直incorrect,应该是(((a*b)%mod)*c)%mod。

另外sum of geo_sum是随着i递增的,不需要对于每个A[i]都重新算,直接累加A[i]对应的贡献值即可。

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
//Problem C. Kickstart Alarm Kickstart 2018 round C
const int maxn=1000010;
int N;
int T;
long long C;
int K;
long long D;
long long F;
long long E1;
long long E2;
long long x1;
long long y1;
long long A[maxn];
const long long mod=1000000007;
long long presum[maxn];
long long inv[maxn];//1/a % mod=a^(p-2)
long long ans;
long long pow_mod(long long a,long long b)
{
    long long s=1;
    long long t=1;
    while(b)
    {
        if(b&t)
        {
            s=(s*a)%mod;
        }
        a=(a*a)%mod;
        b=b>>1;
    }
    return s;
}
long long power_sum(long long x)
{
    if(x==1)
    {
        return (long long)K;
    }
    else
    {
        long long ret=((x*((pow_mod(x,K)-1)%mod)%mod)*inv[x-1])%mod;//need to mod after each production, avoid overflow
        if(ret<0)//why this can happen? if use pow_mod(x,K+1)-x, pow_mod(x,K+1)-x is after mod, may be less than x
        {
            cout<<(pow_mod(x,K)-1)<<" "<>T;
    for(int i=1;i<=1000010;i++)
    {
        inv[i]=pow_mod(i,mod-2)%mod;
    }
    for(int ca=1;ca<=T;ca++)
    {
        scanf("%d %d %lld %lld %lld %lld %lld %lld %lld", &N, &K, &x1, &y1, &C, &D, &E1, &E2, &F);
        memset(A,0,sizeof(A));
        ans=0;
        A[1]=(x1+y1)%F;
        for(int i=2;i<=N;i++)
        {
            int prex1=x1;
            int prey1=y1;
            x1=(C*prex1+D*prey1+E1)%F;
            y1=(D*prex1+C*prey1+E2)%F;
            A[i]=(x1+y1)%F;
        }
//        for(int i=1;i<=N;i++)
//        {
//            presum[i]=presum[i-1]+A[i];
//        }
        long long geo_sum=0;
        for(int i=1;i<=N;i++)
        {
//            if(power_sum(i)<0)
//            {
//                cout<<"here"<

 

你可能感兴趣的:(Problem C. Kickstart Alarm Google Kickstart Round C 2018)