codeforces 710D Two Arithmetic Progressions(线性同余方程)

题目链接:

http://codeforces.com/problemset/problem/710/D

分析:给你两个方程 a1k + b1 and a2l + b2,求在一个闭区间【L,R】中有多少个X,X满足 x = a1k‘ + b1 = a2l‘ + b2

由此可以发现这两个方程满足线性同余,即 x ≡b1mod(a1) 且 x≡b2mod(a2); 也就是 a1k‘ + b1 = a2l‘ + b2a.

所以 a1k1 + (-a2k2) = (b2 - b1),由同余方程得 : X ≡ (b2 - b1) mod(a2).

所以我们可以先求的一个特解x0,然后找到它的最小整数解 x,再把x 放在【L,R】里找出它包含多少个。

对于解线性同余方程:

求特殊解

对于线性同余方程

ax ≡ b (mod n) (1)

若 d = gcd(a, n),d 整除 b ,那么b/d为整数。由裴蜀定理,存在整数对 (r,s) (可用辗转相除法求得)使得 ar+sn=d,因此 x0=rb/d是方程 (1) 的一个解。其他的解都关于n/d与 x 同余。即x≡x0+(n/d)*t (mod n) (0≤t≤d-1)。

举例来说,方程

12x ≡ 20 (mod 28)

中 d = gcd(12,28) = 4 。注意到 4 = 12 *(-2)+28*1,因此 x0≡5*(-2)≡-10≡4(mod 7)是一个解。对模 28 来说,t=1,x≡4+(28/4)*1≡11 (mod 28);t=2,x≡4+(28/4)*2≡18 (mod 28);t=3,x≡4+(28/4)*3≡25 (mod 28) 。所有的解就是 {4,11,18,25} 。

附:取模运算

int mod(int a,int b)
{
if(a >= 0)
      return a % b;
else
      return a % b + b;
}

线性同余方程

对于方程 a*x+b*y=n;有整数解得充分必要条件是(n %(a,b)==0),这个定理这里就不证明了,数论书上都有。

所以方程 a*x+b*y=n;我们可以先用扩展欧几里德算法求出一组x0,y0。也就是a*x0+b*y0=(a,b);然后两边同时除以(a,b),再乘以n。这样就得到了方程a*x0*n/(a,b)+b*y0*n/(a,b)=n;我们也就找到了方程的一个解。

还有一个定理:若(a,b)=1,且x0,y0为a*x+b*y=n的一组解,则该方程的任一解可表示为:x=x0+b*t,y=y0-a*t;且对任一整数t,皆成立。(这个证明比较简单,就不写了)

这样我们就可以求出方程的所有解了,但实际问题中,我们往往被要求去求最小整数解,所以我们就可以将一个特解x,t=b/(a,b),x=(x%t+t)%t;就可以了。

 1 /*************************************************************************
 2     > File Name: cf710D.cpp
 3     > Author:
 4     > Mail:
 5     > Created Time: 2016年08月27日 星期六 22时28分30秒
 6  ************************************************************************/
 7
 8 #include<iostream>
 9 #include<bits/stdc++.h>
10 using namespace std;
11 typedef long long ll;
12
13 ll exgcd(ll a, ll b, ll& x, ll& y)
14 {
15     ll d = a;
16     if(b!=0)
17     {
18         d = exgcd(b,a % b,y,x);
19         y -= (a / b) * x;
20     }
21     else
22     {
23         x = 1;
24         y = 0;
25     }
26     return d;
27 }
28
29 int main()
30 {
31     ll a1,b1,a2,b2,L,R;
32     cin >> a1 >> b1 >> a2 >> b2 >> L >> R;
33     ll x,y;
34     ll d = exgcd(a1,a2,x,y);
35     if((b2 - b1) % d != 0)
36     {
37         cout << 0 << endl;
38         return 0;
39     }
40     x *=(b2 - b1)/d;
41     ll t = a2/d;
42     x = (x % t + t) %t;
43     ll cnt = a1 * x + b1;
44     ll lcm = a1/d *a2;
45     ll ans = 0;
46     L = max(L,max(b1,b2));
47     if(L > R)
48     {
49         cout << 0 << endl;
50         return 0;
51     }
52     if(cnt <= R) ans += (R-cnt)/lcm +1;//放在区间里找包含多少个解,需要注意方式
53     if(cnt < L) ans -= (L-cnt- 1)/lcm +1;
54     cout << ans << endl;
55     return 0;
56 }
时间: 2024-08-02 15:14:29

codeforces 710D Two Arithmetic Progressions(线性同余方程)的相关文章

【数论】【扩展欧几里得】Codeforces 710D Two Arithmetic Progressions

题目链接: http://codeforces.com/problemset/problem/710/D 题目大意: 两个等差数列a1x+b1和a2x+b2,求L到R区间内重叠的点有几个. 0 < a1, a2 ≤ 2·109,  - 2·109 ≤ b1, b2, L, R ≤ 2·109, L ≤ R). 题目思路: [数论][扩展欧几里得] 据题意可得同余方程组 x=b1(mod a1) 即 x=k1*a1+b1 x=b2(mod a2) x=k2*a2+b2 化简,k1*a1=k2*a2

Dirichlet&#39;s Theorem on Arithmetic Progressions POJ - 3006 线性欧拉筛

题意 给出a d n    给出数列 a,a+d,a+2d,a+3d......a+kd 问第n个数是几 保证答案不溢出 直接线性筛模拟即可 1 #include<cstdio> 2 #include<cstring> 3 using namespace std; 4 bool Is_Primes[1000005]; 5 int Primes[1000005]; 6 int A[1000005]; 7 int cnt; 8 void Prime(int n){ 9 cnt=0; 1

POJ 3006 Dirichlet&#39;s Theorem on Arithmetic Progressions 快筛质数

题目大意:给出一个等差数列,问这个等差数列的第n个素数是什么. 思路:这题主要考如何筛素数,线性筛.详见代码. CODE: #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define MAX 1000010 using namespace std; int prime[MAX],primes; bool notp[MAX]; int a,d,n;

POJ2115 C Looooops【解线性同余方程】

题目链接: http://poj.org/problem?id=2115 题目大意: 对于循环语句: for(int i = A; i != B; i += C) 语句1: 已知i.A.B.C都是k进制的无符号整数类型,给出A.B.C.k的值,计算并输出语句1 的执行次数,如果为无限次,那么直接输出"FOREVER". 思路: 设算法执行X步,那么题目就变为求解A + CX ≡ B( mod M)(M= 2^k).即A + CX + MY ≡ B. CX + MY ≡ B - A(M

poj 3006 Dirichlet&#39;s Theorem on Arithmetic Progressions

Description If a and d are relatively prime positive integers, the arithmetic sequence beginning with a and increasing by d, i.e., a, a + d, a + 2d, a + 3d, a + 4d, ..., contains infinitely many prime numbers. This fact is known as Dirichlet's Theore

(素数求解)I - Dirichlet&#39;s Theorem on Arithmetic Progressions(1.5.5)

Time Limit:1000MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I64u Submit Status Description If a and d are relatively prime positive integers, the arithmetic sequence beginning with a and increasing by d, i.e., a, a + d, a + 2d, a + 3d, a 

POJ 1061 - 青蛙的约会 - [exgcd求解一元线性同余方程]

先上干货: 定理1: 如果d = gcd(a,b),则必能找到正的或负的整数k和l,使ax + by = d. (参考exgcd:http://www.cnblogs.com/dilthey/p/6804137.html) 定理2: 一元线性同余方程ax ≡ n (mod b) 有解,当且仅当gcd(a,b)|n. 也就是说,解出了ax+by=gcd(a,b),就相当于解出了ax≡n(mod b) (而且只要满足gcd(a,b)|n,就一定有解) 定理3: 若gcd(a,b) = 1,则方程ax

POJ 3006 Dirichlet&#39;s Theorem on Arithmetic Progressions 素数 难度:0

http://poj.org/problem?id=3006 #include <cstdio> using namespace std; bool pm[1000002]; bool usd[1000002]; bool judge(int x) { if(usd[x])return pm[x]; usd[x] = true; if(x == 2) return pm[x] = true; if(((x & 1) == 0) || (x < 2))return pm[x] =

洛谷P1214 [USACO1.4]等差数列 Arithmetic Progressions

P1214 [USACO1.4]等差数列 Arithmetic Progressions• o 156通过o 463提交• 题目提供者该用户不存在• 标签USACO• 难度普及+/提高 提交 讨论 题解 最新讨论• 这道题有问题• 怎么进一步优化时间效率啊 …题目描述一个等差数列是一个能表示成a, a+b, a+2b,..., a+nb (n=0,1,2,3,...)的数列.在这个问题中a是一个非负的整数,b是正整数.写一个程序来找出在双平方数集合(双平方数集合是所有能表示成p的平方 + q的平