P7887-「MCOI-06」Existence of Truth【構造】


正題

題目連接: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\)那么有

\[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_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\)來得到解數。


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\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;
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM