exgcd应用

这篇博客探讨了如何高效地求解模意义下的一元一次同余方程,给出了欧几里得算法实现,并通过实例展示了如何找到最小正整数解。此外,还介绍了两个闹钟同步问题的数学模型,以及红黑胡椒问题的优化策略,涉及最大总味觉的计算。所有问题都与数论和算法紧密相关。
摘要由CSDN通过智能技术生成

题目描述

求关于xx的同余方程 a x \equiv 1 \pmod {b}ax≡1(modb) 的最小正整数解。

输入格式

一行,包含两个正整数 a,ba,b,用一个空格隔开。

输出格式

一个正整数 x_0x0​,即最小正整数解。输入数据保证一定有解。

输入输出样例

输入 #1复制

3 10

输出 #1复制

7

说明/提示

【数据范围】

对于 40%的数据,2 ≤b≤ 1,0002≤b≤1,000;

对于 60%的数据,2 ≤b≤ 50,000,0002≤b≤50,000,000;

对于 100%的数据,2 ≤a, b≤ 2,000,000,0002≤a,b≤2,000,000,000。

NOIP 2012 提高组 第二天 第一题

#include<iostream>
using namespace std;
#define int long long
int x,y;
int exgcd(int a,int b)
{
    if(!b)
    {
        x=1,y=0;
        return a;
    }
    exgcd(b,a%b);
    int tx=x;
    x=y;
    y=tx-(a/b)*y;
}
signed main()
{
    int a,b;cin>>a>>b;
    exgcd(a,b);
    cout<<(x%b+b)%b<<endl;
    return 0;
}

有两个闹钟。

第一个闹钟会在 b,b+a,b+2a,b+3a,…b,b+a,b+2a,b+3a,… 时刻响铃。

第二个闹钟会在 d,d+c,d+2c,d+3c,…d,d+c,d+2c,d+3c,… 时刻响铃。

请计算两个闹钟第一次同时响铃的具体时刻。

输入格式

第一行包含两个整数 a,ba,b。

第二行包含两个整数 c,dc,d。

输出格式

一个整数,表示第一次同时响铃的具体时刻。

如果永远都不可能同时响铃,则输出 −1−1。

#include<iostream>
using namespace std;
int x,y;
int kk;
void exgcd(int a,int b)
{
    if(!b)
    {
        kk=a;
        x=1;y=0;
        return ;
    }
    exgcd(b,a%b);
    int tx=x;
    x=y;
    y=tx-(a/b)*y;
}
int main()
{
    int a,b,c,d;
    cin>>a>>b>>c>>d;
    if(b>d) {
        swap(b,d);
        swap(a,c);
    }
    int now=d-b;
    exgcd(a,c);
    if(now%kk!=0)
    {
        cout<<-1<<endl;
        return 0;
    }
    x=x*(now/kk);
    y=y*(now/kk);
    int p=c/kk;
    int pp=a/kk;
    //cout<<x<<" "<<y<<endl;
    x=(x%p+p)%p;
    y=(y%pp+pp)%pp;
    if(y) y-=pp; 
    cout<<-y*c+d<<endl;
    
}

E. Red-Black Pepper

time limit per test

2 seconds

memory limit per test

256 megabytes

input

standard input

output

standard output

Monocarp is going to host a party for his friends. He prepared nn dishes and is about to serve them. First, he has to add some powdered pepper to each of them — otherwise, the dishes will be pretty tasteless.

The ii-th dish has two values aiai and bibi — its tastiness with red pepper added or black pepper added, respectively. Monocarp won't add both peppers to any dish, won't add any pepper multiple times, and won't leave any dish without the pepper added.

Before adding the pepper, Monocarp should first purchase the said pepper in some shop. There are mm shops in his local area. The jj-th of them has packages of red pepper sufficient for xjxj servings and packages of black pepper sufficient for yjyj servings.

Monocarp goes to exactly one shop, purchases multiple (possibly, zero) packages of each pepper in such a way that each dish will get the pepper added once, and no pepper is left. More formally, if he purchases xx red pepper packages and yy black pepper packages, then xx and yy should be non-negative and x⋅xj+y⋅yjx⋅xj+y⋅yj should be equal to nn.

For each shop, determine the maximum total tastiness of the dishes after Monocarp buys pepper packages only in this shop and adds the pepper to the dishes. If it's impossible to purchase the packages in the said way, print -1.

Input

The first line contains a single integer nn (1≤n≤3⋅1051≤n≤3⋅105) — the number of dishes.

The ii-th of the next nn lines contains two integers aiai and bibi (1≤ai,bi≤1091≤ai,bi≤109) — the tastiness of the ii-th dish with red pepper added or black pepper added, respectively.

The next line contains a single integer mm (1≤m≤3⋅1051≤m≤3⋅105) — the number of shops.

The jj-th of the next mm lines contains two integers xjxj and yjyj (1≤xj,yj≤n1≤xj,yj≤n) — the number of servings the red and the black pepper packages are sufficient for in the jj-th shop, respectively.

Output

Print mm integers. For each shop, print the maximum total tastiness of the dishes after Monocarp buys pepper packages only in this shop and adds the pepper to the dishes. If it's impossible to purchase the packages so that each dish will get the pepper added once and no pepper is left, print -1.

#include<iostream>
#include<cstring>
#include<cstdio>
#include<string>
#include<map>
#include<queue>
using namespace std;
const int N=3e5+5;
typedef long long ll;
int a[N],b[N];
ll c[N];
int gcd(int a,int b)
{
    return b?gcd(b,a%b):a;
}
ll x,y;
int exgcd(int a,int b)
{
    if(!b)
    {
        x=1,y=0;
        return a;
    }
    exgcd(b,a%b);
    int tx=x;
    x=y;
    y=tx-(a/b)*y;
}
void solve()
{
    priority_queue<int> q;
    int n;cin>>n;
    for(int i=1;i<=n;i++) cin>>a[i]>>b[i],q.push(b[i]-a[i]),c[0]+=a[i];
    int mid=0,num=0;
    while(!q.empty())
    {
        int now=q.top();q.pop();
        if(now>=0) mid++;
        c[num+1]=c[num]+now;
        num++;
    }
    int m;cin>>m;
    while(m--)
    {
        int tx,ty;
        cin>>tx>>ty;
        swap(tx,ty);
        int d=gcd(tx,ty);
        if(n%d) cout<<-1<<'\n';
        else
        {
            ll ans=0;
            exgcd(tx,ty);
            x=x*n/d;
            int ky=ty/d,kx=tx/d;
            x=(x%ky+ky)%ky;
            y=(n-tx*x)/ty;
            if(y<0) cout<<-1<<'\n';
            else
            {
                int mn=x*tx,mx;
                y=y%kx;
                x=(n-ty*y)/tx;
                mx=x*tx;
                if(mx<=mid) ans=max(ans,c[mx]);
                else if(mn>=mid) ans=max(ans,c[mn]);
                else
                {
                    int now=(mx-mid)/(ky*tx);
                    mx=mx-now*(ky*tx);
                    ans=max(ans,c[mx]);
                    mx-=ky*tx;
                    if(mx>=0)
                    ans=max(ans,c[mx]);
                }
                cout<<ans<<'\n';
            }
        }
    }
}
int main()
{
    ios_base::sync_with_stdio(false);
    cin.tie(0),cout.tie(0);
    solve();
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值