zoukankan      html  css  js  c++  java
  • CF710D Two Arithmetic Progressions

    原题链接

    即求在([L,R])之间有多少个整数(K)满足(K = a_1x + b_1 = a_2y + b_2),其中(x,y)为自然数
    很容易想到将等式移项,变为(a_1x + a_2(-y) = b_2 - b_1)
    那么很明显可以用扩欧来求出一组(x,y)的特解,并将特解移至自然数范围内的最小解
    因为原式是等式,接下来我们只需要关注其中一个解,例如(x)
    设扩欧求出的(x)的通解为(x_0 + k imes MOD),其中(MOD = a_2/gcd),因为特解(x_0)是摸(MOD)下最小自然数解,所以(k)也为自然数
    题目要求的是([L,R])之间有多少个整数(K)满足(K = a_1x + b_1)
    将通解代入,即求([L,R])之间有多少个整数(K)满足(K = (a_1MOD)k + a_1x_0 + b_1)
    那么最后就是求有多少(k)能让整数落于([L,R]),因为(k)连续,所以直接算不大于(R)的最大(k)和不小于(L)的最小(k)即可
    写成公式就是(leftlfloordfrac{R - (a_1x_0 + b_1)}{a_1MOD} ight floor - leftlceildfrac{L - (a_1x_0 + b_1)}{a_1MOD} ight ceil + 1)
    但要注意可能会除出来负数,因为(k)为自然数,要手动调到(0),具体见代码。

    #include<cstdio>
    #include<cmath>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    const int N = 1e5 + 10;
    const int mod = 1073741824;
    inline ll re()
    {
    	ll x = 0;
    	char c = getchar();
    	bool p = 0;
    	for (; c < '0' || c > '9'; c = getchar())
    		p |= c == '-';
    	for (; c >= '0' && c <= '9'; c = getchar())
    		x = x * 10 + c - '0';
    	return p ? -x : x;
    }
    ll exgcd(ll a, ll b, ll& x, ll& y)
    {
    	if (!b)
    	{
    		x = 1; y = 0;
    		return a;
    	}
    	ll gcd = exgcd(b, a % b, y, x);
    	y -= a / b * x;
    	return gcd;
    }
    int main()
    {
    	ll i, j, k, n, m, a_1, a_2, b_1, b_2;
    	a_1 = re(); b_1 = re(); a_2 = re();
    	b_2 = re(); n = re(); m = re();
    	ll x, y, gcd = exgcd(a_1, a_2, x, y);
    	if ((b_2 - b_1) % gcd)//无解
    		return printf("0"), 0;
    	x *= (b_2 - b_1) / gcd;//一组特解
    	y *= (b_2 - b_1) / gcd;
    	ll MOD = a_2 / gcd;
    	x = (x % MOD + MOD) % MOD;//先让x落于自然数范围
    	y = -((b_2 - b_1) - a_1 * x) / a_2;//算出此时的y
    	if (y < 0)//若y还是负数就让y落于自然数范围并计算出x,此时x一定为自然数
    	{
    		ll MODY = a_1 / gcd;
    		y = (y % MODY + MODY) % MODY;
    		x = ((b_2 - b_1) + a_2 * y) / a_1;
    	}
    	m = floor(1.0 * (m - a_1 * x - b_1) / (a_1 * MOD));//计算最大的k
    	if (m < 0)//不大于右边界的最大k都为负,那么一定不存在解
    		return printf("0"), 0;
    	n = ceil(1.0 * (n - a_1 * x - b_1) / (a_1 * MOD));//计算最小的k
    	if (n < 0) n = 0;//k不能小于0
    	printf("%lld", m - n + 1);
    	return 0;
    }
    
  • 相关阅读:
    不允许使用邮箱名称。 服务器响应为: Mail from must equal authorized user
    SQL SERVER MD5
    c#转VB.NET
    SQL Sqlserver查询的安全性和性能的优化(转载)
    SQL Server 开发人员需要避免的八种习惯(TechTarget转载)
    索引维护对于保证查询能够总是受益于索引使用并减少 IO/RAM/CPU 是至关重要的
    SQL SERVER性能分析--死锁检测数据库阻塞语句
    怎样有效地跟踪SQL Server的阻塞问题?(网转)
    solr.net的使用
    利用HttpWebRequest实现实体对象的上传
  • 原文地址:https://www.cnblogs.com/Iowa-Battleship/p/14279175.html
Copyright © 2011-2022 走看看