zoukankan      html  css  js  c++  java
  • poj2891 Strange Way to Express Integers poj1006 Biorhythms 同余方程组

    怎样求同余方程组?如:

    [egin{cases} x equiv a_1 pmod {m_1} \ x equiv a_2 pmod {m_2} \ cdots \ x equiv a_n pmod {m_n} end{cases}]

    不保证 (m) 两两互素?
    两两合并!
    比方说

    [egin{cases} x equiv a_1 pmod {m_1} \ x equiv a_2 pmod {m_2} \ end{cases}]

    就是

    [egin{cases} x = m_1x_1+a_1\ x = m_2x_2+a_2\ end{cases}]

    可以变形成

    [m_1x_1+m_2(-x_2)=a_2-a_1 ]

    拿扩欧搞掉这个方程。我们肯定想让 (x) 最小,那就让 (x_1) 最小,这样就求出了 (x) 的特解 (x')
    显然, (x) 的通解是 (x=x'+[m_1,m_2] imes t ,t in mathbb{Z})
    这也就很像是

    [x equiv x' pmod {[m_1,m_2]} ]

    我们惊喜地发现两个方程变成了一个方程。一路做下去就好了。

    #include <iostream>
    #include <cstdio>
    using namespace std;
    typedef long long ll;
    int n;
    ll a, r, m, aa, rr, x, y;
    bool flag;
    ll exgcd(ll a, ll b, ll &x, ll &y){
    	if(!b){
    		x = 1;
    		y = 0;
    		return a;
    	}
    	ll re=exgcd(b, a%b, x, y);
    	ll z=x;
    	x = y;
    	y = z - a / b * y;
    	return re;
    }
    int main(){
    	while(scanf("%d", &n)!=EOF){
    		flag = true;
    		n--;
    		scanf("%lld %lld", &aa, &rr);
    		while(n--){
    			scanf("%lld %lld", &a, &r);
    			if(!flag)	continue;
    			ll gcd=exgcd(aa, a, x, y);
    			if((r-rr)%gcd)	flag = false;
    			else
    				x = (((r-rr)/gcd*x)%(a/gcd)+a/gcd)%(a/gcd);
    			x = rr + x * aa;
    			rr = x;
    			aa = a/gcd*aa;
    		}
    		if(flag)	printf("%lld
    ", x);
    		else	printf("-1
    ");
    	}
    	return 0;
    }
    

    如果保证两两互素呢?那就中国剩余定理了。记 (m =prod_{i=1}^n m_i)(M_i=m/m_i)(t_i)(M_i) 在模 (m_i) 意义下的乘法逆元,则一个特解是 (sum_{i=1}^n a_iM_it_i)。通解是 (sum_{i=1}^n a_iM_it_i + mk, k in mathbb{Z})
    证明:因为当 (i ot =j)时,(m_j|M_i),则 (a_iM_it_i equiv 0 pmod {m_j}),而 (a_jM_jt_j equiv a_j pmod {m_j}),证毕。

    #include <iostream>
    #include <cstdio>
    using namespace std;
    int a[15], cnt, mul, ans, x, y, dd;
    const int m[]={0, 23, 28, 33};
    int exgcd(int aa, int bb, int &x, int &y){
    	if(!bb){
    		x = 1;
    		y = 0;
    		return aa;
    	}
    	int re=exgcd(bb, aa%bb, x, y);
    	int z=x;
    	x = y;
    	y = z - aa / bb * y;
    	return re;
    }
    int ni(int aa, int bb){
    	int gcd=exgcd(aa, bb, x, y);
    	return (x%bb+bb)%bb;
    }
    int main(){
    	while(scanf("%d %d %d %d", &a[1], &a[2], &a[3], &dd)!=EOF){
    		mul = 1;
    		if(a[1]<0)	break;
    		ans = 0;
    		for(int i=1; i<=3; i++)
    			a[i] %= m[i], mul *= m[i];
    		for(int i=1; i<=3; i++)
    			ans += a[i] * (mul/m[i])%mul * ni(mul/m[i], m[i])%mul;
    		ans -= dd;
    		ans = (ans%mul+mul)%mul;
    		if(!ans)	ans += mul;
    		printf("Case %d: the next triple peak occurs in %d days.
    ", ++cnt, ans);
    	}
    	return 0;
    }
    
  • 相关阅读:
    [gym102832J]Abstract Painting
    [atARC070E]NarrowRectangles
    [atARC070F]HonestOrUnkind
    Cupid's Arrow[HDU1756]
    Surround the Trees[HDU1392]
    TensorFlow-正弦函数拟合
    某新版本不兼容老版本代码的语言的一点基础了解
    TensorFlow安装
    离散快速傅里叶变换
    2016"百度之星"
  • 原文地址:https://www.cnblogs.com/poorpool/p/8509942.html
Copyright © 2011-2022 走看看