简介:在数论中,裴蜀定理是一个关于最大公约数(或最大公约式)的定理。裴蜀定理得名于法国数学家艾蒂安·裴蜀,说明了对任 何整数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
题解:通过观察 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
题解:通过观察,(±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;
}