正题
题目连接:https://www.luogu.com.cn/problem/P7887?contestId=52021
题目大意
给出三个长度为(n)的序列(x_i,y_i,z_i),求一个序列(a)满足(0leq a_i<10^9+7)且
[x_ileft(sum_{j=1}^ia_j
ight)+y_ileft(sum_{j=i}^na_j
ight)equiv z_i(mod 10^9+7)
]
如果只有一组解就输出这组解
(1leq sum nleq 2 imes 10^5,1leq x_i,y_i<10^9+7,0leq z_i<10^9+7)
解题思路
看到这个同余就感觉这题是个啥方程的做法类的
设(s_i=sum_{j=1}^ia_j)那么有
[x_is_i+y_i(s_n-s_{i-1})=z_i
]
这样我们就有了(s_i,s_{i-1},s_n)之间的关系式,而对于(s_1)我们可以直接得到它和(s_n)的关系式
[x_1s_1+y_1s_n=z_1Rightarrow s_1=frac{z_1-y_1s_n}{x_1}
]
这样我们可以设(s_i=A_i+B_is_n),然后用上面的式子化为
[s_i=frac{z_i+y_is_{i-1}-y_is_n}{x_i}
]
推出后面的(A,B),最后有
[s_n=A_n+B_ns_nRightarrow s_n=frac{A_n}{1-B_n}
]
当然(B_n=1)时需要判断(A_n)是否为(0)来得到解数。
code
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
const ll N=2e5+10,P=1e9+7;
ll T,n,x[N],y[N],z[N],a[N],b[N],s[N];
ll power(ll x,ll b){
ll ans=1;x%=P;
while(b){
if(b&1)ans=ans*x%P;
x=x*x%P;b>>=1;
}
return ans;
};
signed main()
{
scanf("%lld",&T);
while(T--){
scanf("%lld",&n);
for(ll i=1;i<=n;i++)
scanf("%lld%lld%lld",&x[i],&y[i],&z[i]);
ll inv=power(x[1],P-2);
a[1]=z[1]*inv%P;b[1]=(P-y[1])*inv%P;
for(ll i=2;i<=n;i++){
inv=power(x[i],P-2);
a[i]=(a[i-1]*y[i]%P+z[i])*inv%P;
b[i]=(b[i-1]*y[i]%P-y[i]+P)%P*inv%P;
}
if(b[n]==1){printf("%lld
",a[n]?0:P);continue;}
s[n]=a[n]*power((1-b[n]+P)%P,P-2)%P;
for(ll i=1;i<n;i++)
s[i]=(a[i]+b[i]*s[n]%P)%P;
puts("1");
for(ll i=1;i<=n;i++)
printf("%lld ",(s[i]-s[i-1]+P)%P);
putchar('
');
}
return 0;
}