这一题把公式拆开是可以找到规律的。我开始找出了固定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<iostream>
#include<stdio.h>
#include<cstdio>
#include<string>
#include<cmath>
#include<stdlib.h>
#include<algorithm>
#include<string.h>
#include<cstring>
#include<vector>
#include<queue>
#include<map>
#include<set>
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)<<" "<<x<<" "<<inv[x-1]<<endl;
ret+=mod;
}
return ret;
}
}
int main()
{
// freopen("input.txt","r",stdin);
freopen("C-large-practice.in","r",stdin);
freopen("C.txt","w",stdout);
cin>>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"<<endl;
// }
geo_sum+=power_sum(i);
geo_sum%=mod;
ans+=((A[i]*(N-i+1)%mod)*geo_sum)%mod;//previous forgot to mod after the first production, use (A[i]*(N-i+1)*geo_sum)%mod, cause error, may be overflow
ans%=mod;
}
// for(int l=1;l<=N;l++)
// {
// for(int x=1;x<=l;x++)
// {
// ans+=(power_sum(x)%mod)*(presum[N-l+x]-presum[x-1])%mod;
// ans%=mod;
// }
// }
// for(int i=0;i<N;i++)
// {
// cout<<A[i]<<" ";
// }
// cout<<endl;
// for(int k=0;k<K;k++)
// {
// //cout<<"k "<<k+1<<endl;
// for(int i=1;i<=N;i++)
// {
// for(int j=i+1;j<=N;j++)//A[i,..,j-1]
// {
// for(int l=i;l<j;l++)
// {
// long long a=l-i+1;
// long long b=k+1;
// //cout<<"a "<<a<<" b "<<b<<" "<<pow_mod(a,b)<<endl;
// long long tmp=A[l]*pow_mod(a,b)%mod;
// //cout<<"i "<<i<<" j "<<j<<" l "<<l<<" A[l] "<<A[l]<<" tmp "<<tmp<<endl;
// power[k]+=tmp;
// power[k]%=mod;
// }
// }
// }
// }
// for(int i=0;i<K;i++)
printf("Case #%d: %d\n", ca, ans);
cerr<<"case "<<ca<<endl;
}
return 0;
}