[TJOI2009]猜数字

Posted oierwyh

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[TJOI2009]猜数字相关的知识,希望对你有一定的参考价值。

[TJOI2009]猜数字

中国剩余定理+龟速乘

这个大概就是中国剩余定理的板子题了啊。。。

中国剩余定理:

问题:

\(m_1,m_2...m_n,\)是两两互质的正整数,

求解线性同余方程组:

\[f(n)=\begincases x\equiv a_1\pmod m_1\x\equiv a_2\pmod m_2\... ...\x\equiv a_n\pmod m_n\\endcases\]

的解\(x\)

解法:

\(M=\prod_i=1^n,M_i=M/m_i\)

\(t\)是同余方程\(M_it_i\equiv 1\pmod m_i\)的一个解

关于怎么解同余方程

然后答案就是

\[x=\sum_i=1^n a_im_it_i\]

证明:

因为\(M_i\)是处\(m_i\)外所有数的倍数,所以

\[\forall k\not=i,a_iM_it_i\equiv 0\pmod m_k\]

而且

\[a_iM_it_i\equiv a_i\pmod m_i\]
\[x=\sum_i=1^na_iM_it_i\]

原方程成立。

通解:

\[x=\sum_i=1^n a_im_it_i\]

是问题的一个特殊解,通解为

\[x+kM(k\in Z)\]

证明:

显然(大雾)

龟速乘:

\(O(logn)\)的其他题解里都有,很好理解,就不说了。

\(O(1)\)的龟速乘:

当两个数乘起来爆 long long 的时候,需要用快速乘,虽然O(1)的比O(logn)的快了许多,但是他还是没有普通乘快,所以我叫他龟速乘qwq

Code


inline ll qmul(ll x,ll y,ll mod)

    x%=mod;y%=mod;
    return ((x*y-(ll)(((long double)x*y+0.5)/mod)*mod)%mod+mod)%mod;

这个。。。也挺好理解啊,而且也没法解释啊qwq可意会不可言传

然后就是打板子了emmmm

Code

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;

typedef long long ll;
typedef long double ld;

const int N = 1e5+1;
ll n,ans;
ll M=1,Mi,a[N],m[N];

inline void file()
freopen("text.in","r",stdin);freopen("text.out","w",stdout);
inline void closefile()
fclose(stdin);fclose(stdout);

inline void readx(ll &x)

    x=0;int s=1;char ch=getchar();
    while(ch<'0'||ch>'9')
    if(ch=='-') s=-1;ch=getchar();
    while(ch>='0'&&ch<='9')
    x=(x<<1)+(x<<3)+ch-'0';ch=getchar();
    x*=s;


inline ll qmul(ll x,ll y,ll mod)

    x%=mod;y%=mod;
    return ((x*y-(ll)(((long double)x*y+0.5)/mod)*mod)%mod+mod)%mod;


inline void exgcd(ll a,ll b,ll &x,ll &y)

    if(b==0) x=1;y=0;return;
    exgcd(b,a%b,y,x);
    y=y-a/b*x;


inline void china()

    for(ll i=1;i<=n;++i) readx(a[i]);
    for(ll i=1;i<=n;++i)
    
        readx(m[i]);
        a[i]=(a[i]%m[i]+m[i])%m[i];
        M*=m[i];
    
    for(ll i=1;i<=n;++i)
    
        Mi=M/m[i];
        ll x,y;
        exgcd(Mi,m[i],x,y);
        x=(x%m[i]+m[i])%m[i];
        ans=((ans+qmul(qmul(a[i],x,M),Mi,M)%M)+M)%M;
    
    ans=(ans+M)%M;
    printf("%lld\n",ans);


int main()

//  file();

    readx(n);
    china();

//  closefile();
    return 0;

以上是关于[TJOI2009]猜数字的主要内容,如果未能解决你的问题,请参考以下文章

P3868 [TJOI2009]猜数字

[Luogu3868] [TJOI2009]猜数字

P3868 [TJOI2009]猜数字

P3868 [TJOI2009]猜数字(中国剩余定理)

中国剩余定理

用Java编程这个猜数字游戏