二元一次不定方程
定义:是整数,,那么形如的方程称为二元一次不定方程。
定理:设是整数,且,如果,那么方程存在无数多个整数解,否则方程不存在整数解。
二元一次不定方程和同余方程之间可以相互转换的,例如在的条件下,求解二元一次不定方程与求解同余方程是相同的。
求解同余方程使用扩展欧几里得算法,二元一次不定方程同样可以使用扩展欧几里得算法。
由扩展欧几里得可知:设和不全为0,则存在整数,使得:
所以当时,存在整数解。
通过扩展欧几里得算法求出特解,那么通解为.
void exgcd(int a,int b,int&d,int&x,int&y)//扩展欧几里得算法
{
if(b==0)
{
x=1,y=0;
d=a;
}
else
{
exgcd(b,a%b,d,x,y);
int t=x;
x=y;
y=t-a/b*y ;
}
}
元一次不定方程
定理:元一次不定方程,有解的充分必要条件是.
解元一次不定方程可以转化为求二元一次不定方程,元一次不定方程,可以转为为下面形式:
,所以上述定理成立。
求出最后一个方程的解,然后代入倒数第二个方程,依此类推可以求出方程的所有解。
对于个元一次不定方程组成的方程组,其中,可以消去个未知数,从而消去个不定方程,将方程组转化为一个元的一次不定方程。然后依照元一次不定方程求解。
解不定方程简单应用
The Balance(poj 2142)
有一天平,两个质量为和的砝码,数量不限,且两边都可以放,要求称出质量为的物品,即两边平衡。尽量少的使用砝码,当砝码数量相同时总重量最小。
输入为.
思路:如果a小于b交换a,b。显然可以构造不定方程,此时和不一定为正整数,可以先求出一组特解,通解就为.因为要求砝码数尽量少,即,代入通解为,因为,显然最小值应在附近,可以for循环枚举前后的几个值,然后取,当相等时
代码如下:
#include <iostream>
#include <algorithm>
#include <math.h>
using namespace std;
typedef long long ll;
const int maxx=1e6+7;
void exgcd(ll a,ll b,ll&d,ll&x,ll&y)
{
if(!b)
{
x=1,y=0;
d=a;
}
else
{
exgcd(b,a%b,d,x,y);
ll temp=x;
x=y;
y=temp-a/b*y;
}
}
int main()
{
ll a,b,c,d,x0,y0;
ios::sync_with_stdio(false);
while(cin>>a>>b>>c&&(a||b||c))
{
ll x=0x3f3f3f3f,y=0x3f3f3f3f,flag=0;
if(a<b) {swap(a,b);flag=1;}
exgcd(a,b,d,x0,y0);
a=a/d;
b=b/d;
x0=x0*c/d;
y0=y0*c/d;
for(ll i=y0/a-10;i<=y0/a+10;i++)
{
ll q=x0+i*b,p=y0-i*a;
q=q<0?(-q):q; p=p<0?(-p):p;
if(q+p<x+y)
x=q,y=p;
else if(q+p==x+y&&(q*a+p*b)<(x*a+y*b))
x=q,y=p;
}
if(!flag)
cout<<x<<" "<<y<<endl;
else cout<<y<<" "<<x<<endl;
}
}
跳骚(poj 1091)
Z城市居住着很多只跳蚤。在Z城市周六生活频道有一个娱乐节目。一只跳蚤将被请上一个高空钢丝的正中央。钢丝很长,可以看作是无限长。节目主持人会给该跳蚤发一张卡片。卡片上写有N+1个自然数。其中最后一个是M,而前N个数都不超过M,卡片上允许有相同的数字。跳蚤每次可以从卡片上任意选择一个自然数S,然后向左,或向右跳S个单位长度。而他最终的任务是跳到距离他左边一个单位长度的地方,并捡起位于那里的礼物。
比如当N=2,M=18时,持有卡片(10, 15, 18)的跳蚤,就可以完成任务:他可以先向左跳10个单位长度,然后再连向左跳3次,每次15个单位长度,最后再向右连跳3次,每次18个单位长度。而持有卡片(12, 15, 18)的跳蚤,则怎么也不可能跳到距他左边一个单位长度的地方。
当确定N和M后,显然一共有M^N张不同的卡片。现在的问题是,在这所有的卡片中,有多少张可以完成任务。
输入两个整数N和M(N <= 15 , M <= 100000000)。
思路:假设卡片上面数字为,跳骚选择卡片的次数为,那么有不定方程,即,可以计算出的所有情况,然后用减去即可。计算的所有情况可以使用容斥定理计算,如果gcd不等于1的话,那么这些数肯定都至少有一个M的质因子,假设d是M的一个质因子,那么小于M的可以整除d的数个数量就是个,从其中任选n个,因为可以重复选择,所以数量就是。
所以
由容斥原理可知:
#include <iostream>
#include <algorithm>
#include <math.h>
using namespace std;
typedef long long ll;
const int maxx=1e6+7;
ll n,m,p[35],cnt,sum,ans;
ll qpow(ll a,ll b)
{
ll ans=1;
while(b)
{
if(b&1)
ans=ans*a;
a=a*a;
b>>=1;
}
return ans;
}
void dfs(int now,int id,int over,ll product)
{
if(now==over)
{
sum+=qpow(m/product,n);
return;
}
for(int i=id;i<=cnt;i++)
{
dfs(now+1,i+1,over,product*p[i]);
}
}
int main()
{
ios::sync_with_stdio(0);
cin>>n>>m;
ll a=m;
for(int i=2;i*i<=a;i++)
if(a%i==0)
{
p[++cnt]=i;
while(a%i==0)
a/=i;
}
if(a>1) p[++cnt]=a;
for(int i=1;i<=cnt;i++)
{
sum=0;
dfs(0,1,i,1);
if(i&1)
ans+=sum;
else ans-=sum;
}
cout<<qpow(m,n)-ans<<endl;
}
特殊的不定方程
-
毕达哥拉斯定理:平面上的一个直角三角形中,两个直角边边长的平方加起来等于斜边长的平方。如果设直角三角形的两条直角边长度分别是和,斜边长度是,那么可以用数学语言表达:.
满足上面这个方程的正整数三元组被称为毕达哥拉斯三元组。
如果一个毕达哥拉斯三元组,满足,那么这个毕达哥拉斯三元组被称为本原的毕达哥拉斯三元组。
定理:正整数构成一个本原毕达哥拉斯三元组且y为偶数,当且仅当存在互质的正整数其中为奇数,为偶数;或者为奇数,为偶数,并且满足: -
费马大定理:方程无非0整数解,其中为整数且.
-
佩尔方程:形如(且不为完全平方数)的不定方程称为佩尔方程。
佩尔方程当为完全平方数时,,显然方程无解。
解佩尔方程:
若佩尔方程最小特解是(x_1,y_1),那么可有迭代公式:
即:
我们可以通过矩阵快速幂求出第k个解。
对于特解可以暴力求解:
由,得,即,那么令,代入求解,然后判断是否满足,否则就,直到求出满足的特解。
void find()
{
int x,y=1;
while(1)
{
x=(long long)sqrt(d*y*y+1);
if(x*x-d*y*y==1)
break;
y++;
}
}
来源:CSDN
作者:Crazy_pine
链接:https://blog.csdn.net/weixin_43956585/article/details/104214923