P3868 [TJOI2009]猜数字
首先观察式子\(\forall i \in [1,k]\)有\(b_i|(n-a_i)\)
可以得出\(n-a_i=kb_i\)
\(n-a_i\equiv0(mod \ b_i)\)
\(n \equiv a_i (mob\ b_i)\)
这个式子是不是很眼熟??
没错就是中国剩余定理
\(\begin{cases}n \equiv a_1 (mob\ b_1)\\n \equiv a_2 (mob\ b_2)\\n \equiv a_3 (mob\ b_3)\\……\\n \equiv a_i (mob\ b_i)\end{cases}\)
然后就变得简单了,由中国剩余定理的知识可知
设\(m=\prod\limits_{i=1}^{n}b_i\),\(M_i=m/b_i\),\(t_i\)是线性同余方程\(M_it_i\equiv1(mod \ m_i)\)的一个解
解为\(x=\sum\limits_{i=1}^{n}a_iM_it_i\)
记得用龟速乘
注:上面的中国剩余定理必须在模数两两互质的情况下,如果不互质,请看扩展中国剩余定理
/*
@ author:pyyyyyy
-----思路------
-----debug-------
*/
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=2020;
int n;
int a[N],b[N];
int m=1,M[N],t[N];
void exgcd(int a,int b,int &x,int &y)
{
if(!b)
{
x=1;y=0;
return ;
}
exgcd(b,a%b,x,y);
int z=x;
x=y;y=(z-y*(a/b));
return ;
}
int mul(int x,int y,int mod)
{
int ret=0;
while(y)
{
if(y&1) ret=(ret+x)%mod;
x=(x+x)%mod;
y>>=1;
}
return ret;
}
int ans;
signed main()
{
// freopen(".in","r",stdin);
// freopen(".out","w",stdout);
cin>>n;
for(int i=1;i<=n;++i) cin>>a[i];
for(int i=1;i<=n;++i) cin>>b[i];
for(int i=1;i<=n;++i) m*=b[i];
for(int i=1;i<=n;++i) M[i]=m/b[i];
for(int i=1;i<=n;++i)
{
int x,y;
exgcd(M[i],b[i],x,y);
x=(x%b[i]+b[i])%b[i];
ans+=mul(a[i],mul(M[i],x,m),m);
ans%=m;
}
cout<<ans;
return 0;
}
$$Life \quad is \quad fantastic!$$