(裴蜀定理)ax + by = m 有解,当且仅当 m 是 gcd(a,b) 的倍数

简介:在数论中,裴蜀定理是一个关于最大公约数(或最大公约式)的定理。裴蜀定理得名于法国数学家艾蒂安·裴蜀,说明了对任             何整数a、b和它们的最大公约数d,关于未知数x和y的线性丢番图方程(称为裴蜀等式):

      ax + by = m

      有解当且仅当m是d的倍数。裴蜀等式有解时必然有无穷多个整数解,每组解x、y都称为裴蜀数,可用辗转相除法求得。

      例如,12和42的最大公因子是6,则方程12x + 42y = 6有解。事实上有(-3)×12 + 1×42 = 6及4×12 + (-1)×42 = 6。

      特别来说,方程 ax + by = 1 有解当且仅当整数a和b互素。

      裴蜀等式也可以用来给最大公约数定义:d其实就是最小的可以写成ax + by形式的正整数。这个定义的本质是整环中“理想”的概念。因此对于多项式整环也有相应的裴蜀定理。

题目:Wannafly挑战赛22

A 计数器

链接:https://www.nowcoder.com/acm/contest/160/A
来源:牛客网

题目描述

有一个计数器,计数器的初始值为0,每次操作你可以把计数器的值加上a1,a2,...,an中的任意一个整数,操作次数不限(可以为0次),问计数器的值对m取模后有几种可能。

输入描述:

第一行两个整数n,m
接下来一行n个整数表示a1,a2,...,an
1≤n≤100
1≤m,a1,a2,...,an≤1000000000

输出描述:

输出一个整数表示答案

示例1

输入

复制

3 6
6 4 8

输出

复制

3

题解:a1*k1+a2*k2+a3*k3+a4*k4+....an*kn=P%m  (ki 为系数)

            m/gcd(m,a1,a2,...........an)   即为答案

#include<stdio.h>
#include<queue>
#include<string.h>
#include<algorithm>
#include<set>
#include<map>
#include<math.h>
#include<vector>
#include<bitset>
#include<iostream>
using namespace std;
typedef long long ll;
ll gcd(ll a,ll b){
    if(b==0)
        return a;
    else
        return gcd(b,a%b);
}
int main(){
    ll n,m,a;
    scanf("%lld %lld",&n,&m);
    ll ans=m;
    for(int i=0;i<n;i++){
        scanf("%lld",&a);
        ans=gcd(ans,a);
    }
    printf("%lld\n",m/ans);
    return 0;
}

BZOJ 1441 MIN

Description

给出n个数(A1...An)现求一组整数序列(X1...Xn)使得S=A1*X1+...An*Xn>0,且S的值最小
Input
第一行给出数字N,代表有N个数 下面一行给出N个数
Output
S的最小值
Sample Input
2
4059 -1782
Sample Output

99

题解:常规操作

#include<stdio.h>
#include<queue>
#include<string.h>
#include<algorithm>
#include<set>
#include<map>
#include<math.h>
#include<vector>
#include<bitset>
#include<iostream>
using namespace std;
typedef long long ll;
int gcd(int a,int b){
    if(b==0)  return a;
    return gcd(b,a%b);
}
int main(){
    int n,a;
    scanf("%d",&n);
    int ans;
    for(int i=0;i<n;i++){
        scanf("%d",&a);
        a=abs(a);
        if(i==0)
            ans=a;
        else
            ans=gcd(ans,a);
    }
    printf("%d\n",ans);
    return 0;
}

2257: [Jsoi2009]瓶子和燃料

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 1925  Solved: 1172
[Submit][Status][Discuss]

Description

jyy就一直想着尽快回地球,可惜他飞船的燃料不够了。 
有一天他又去向火星人要燃料,这次火星人答应了,要jyy用飞船上的瓶子来换。jyy
的飞船上共有 N个瓶子(1<=N<=1000) ,经过协商,火星人只要其中的K 个 。 jyy
将 K个瓶子交给火星人之后,火星人用它们装一些燃料给 jyy。所有的瓶子都没有刻度,只
在瓶口标注了容量,第i个瓶子的容量为Vi(Vi 为整数,并且满足1<=Vi<=1000000000 ) 。 
火星人比较吝啬,他们并不会把所有的瓶子都装满燃料。他们拿到瓶子后,会跑到燃料
库里鼓捣一通,弄出一小点燃料来交差。jyy当然知道他们会来这一手,于是事先了解了火
星人鼓捣的具体内容。火星人在燃料库里只会做如下的3种操作:1、将某个瓶子装满燃料;
2、将某个瓶子中的燃料全部倒回燃料库;3、将燃料从瓶子a倒向瓶子b,直到瓶子b满
或者瓶子a空。燃料倾倒过程中的损耗可以忽略。火星人拿出的燃料,当然是这些操作能
得到的最小正体积。 
jyy知道,对于不同的瓶子组合,火星人可能会被迫给出不同体积的燃料。jyy希望找
到最优的瓶子组合,使得火星人给出尽量多的燃料。 

Input

第1行:2个整数N,K,  
第2..N 行:每行1个整数,第i+1 行的整数为Vi  

Output

仅1行,一个整数,表示火星人给出燃料的最大值。

Sample Input

3 2
3
4
4

Sample Output

4

HINT

选择第2 个瓶子和第3个瓶子,火星人被迫会给出4 体积的容量。 

Source

[Submit][Status][Discuss]

题解:通过观察 1, 2 , 3 步 可以得出这是一个辗转相除的过程,即求 gcd ,答案就是在 n 中选 k 个值,得到一个最大的 gcd;

解法:暴力 选取k 个是不行的,应该求出没个数的因子,用 map 或 其他记录 因子出现的次数,选取出现了至少k 次,值大的。

#include<stdio.h>
#include<queue>
#include<string.h>
#include<algorithm>
#include<set>
#include<map>
#include<math.h>
#include<vector>
#include<bitset>
#include<iostream>
using namespace std;
int a[1005];
map<int,int>mapp;
void fun(int n){
    for(int i=1;i*i<=n;i++){
        if(n%i==0){
            mapp[i]++;
            mapp[n/i]++;
        }
    }
}

int main(){
    int n,k;
    scanf("%d %d",&n,&k);
    for(int i=0;i<n;i++){
        scanf("%d",&a[i]);
        fun(a[i]);
    }
    int ans=0;
    map<int,int>::iterator it;
    for(it=mapp.begin();it!=mapp.end();it++){
        if(it->second>=k){
            ans=max(ans,it->first);
        }
    }
    printf("%d\n",ans);
    return 0;
}

2299: [HAOI2011]向量

Time Limit: 10 Sec  Memory Limit: 256 MB
Submit: 1728  Solved: 812
[Submit][Status][Discuss]

Description

给你一对数a,b,你可以任意使用(a,b), (a,-b), (-a,b), (-a,-b), (b,a), (b,-a), (-b,a), (-b,-a)这些向量,问你能不能拼出另一个向量(x,y)。

说明:这里的拼就是使得你选出的向量之和为(x,y)

Input

第一行数组组数t,(t<=50000)

接下来t行每行四个整数a,b,x,y  (-2*109<=a,b,x,y<=2*109)

Output

t行每行为Y或者为N,分别表示可以拼出来,不能拼出来

Sample Input

3

2 1 3 3

1 1 0 1

1 0 -2 3

Sample Output

Y

N

Y

HINT
样例解释:
第一组:(2,1)+(1,2)=(3,3)
第三组:(-1,0)+(-1,0)+(0,1)+(0,1)+(0,1)=(-2,3)

Source

[Submit][Status][Discuss]

题解:通过观察,(±2a,0)(0,±2a) (±2b,0)(0,±2b) (a,b)(b,a)

           总共就四种操作   x±2a,y±2b     x+a,y+b       x+b,y+a    x+a+b,y+a+b  也可以确定二三四操作只会出现一次,那么我们枚                举二三四操作,根据裴蜀定理判断是否符合条件。

#include<stdio.h>
#include<queue>
#include<string.h>
#include<algorithm>
#include<set>
#include<map>
#include<math.h>
#include<vector>
#include<bitset>
#include<iostream>
using namespace std;
typedef long long ll;
ll gcd(ll a,ll b){
    if(b==0)  return a;
    else return gcd(b,a%b);
}

bool fun(ll x,ll y,ll g){
    if(x%g==0&&y%g==0)  return true;
    return false;
}
int main(){
    int t;
    ll a,b,x,y;
    scanf("%d",&t);
    while(t--){
        scanf("%lld %lld %lld %lld",&a,&b,&x,&y);
        ll g=gcd(2*a,2*b);
        if(fun(x,y,g)||fun(x+a,y+b,g)||fun(x+b,y+a,g)||fun(x+a+b,y+a+b,g))
            printf("Y\n");
        else
            printf("N\n");
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/black_horse2018/article/details/81805671
M
^M
M2M