题目连接:https://www.luogu.com.cn/problem/P7887?contestId=52021
给出三个长度为\(n\)的序列\(x_i,y_i,z_i\),求一个序列\(a\)满足\(0\leq a_i<10^9+7\)且
\[x_i\left(\sum_{j=1}^ia_j\right)+y_i\left(\sum_{j=i}^na_j\right)\equiv z_i(mod\ 10^9+7) \]如果只有一组解就输出这组解
\(1\leq \sum n\leq 2\times 10^5,1\leq x_i,y_i<10^9+7,0\leq z_i<10^9+7\)
看到这个同余就感觉这题是个啥方程的做法类的
设\(s_i=\sum_{j=1}^ia_j\)那么有
这样我们就有了\(s_i,s_{i-1},s_n\)之间的关系式,而对于\(s_1\)我们可以直接得到它和\(s_n\)的关系式
\[x_1s_1+y_1s_n=z_1\Rightarrow 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_n\Rightarrow s_n=\frac{A_n}{1-B_n} \]当然\(B_n=1\)时需要判断\(A_n\)是否为\(0\)来得到解数。
#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\n",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('\n'); } return 0; }