数论 day 2 试题解析

exgcd写错成功爆0:)

Input
第一行一个整数T,表示需要求解的方程数。
接下来T 行,每行三个整数:a; b; c 表示一个方程:
ax + by = c
Output
对于每个方程:
• 如果方程无解,输出No
• 如果方程有解,输出四个整数:x1 y1 x2 y2,表示两组解,其中x1 y1 表示x 是最小非负时对应的

解,其中x2 y2 表示y 是最小非负时的解。

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
long long t,x,y;
long long gcd(long long m,long long n)
{
	if (n==0)
	return m;
	return gcd(n,m%n);
}
long long exgcd(long long a,long long b,long long &x,long long &y)
{
	long long cd;
	if (b==0)
	{
		x=1;
		y=0;
		return a;
	}
	else
	{
		long long x0,y0;
		cd=exgcd(b,a%b,x0,y0);
		x=y0;
		y=x0-(a/b)*y0;
	}
	return cd;
}
int main()
{
	freopen("modeq.in","r",stdin);
	freopen("modeq.out","w",stdout);
	scanf("%I64d",&t);
	while (t--)
	{
		long long a,b,c;
		scanf("%I64d%I64d%I64d",&a,&b,&c);
		long long d=gcd(a,b);
		if (c%d!=0)
		{
			printf("No\n");
			continue;
		}
		else
		{
			exgcd(a,b,x,y);
			long long x1=c/d*x;
			long long y1=c/d*y;
			long long x2=c/d*x;
			long long y2=c/d*y;
			x1=(x1%abs(b/d)+abs(b/d))%abs(b/d);
			y1=(c-a*x1)/b;
			printf("%I64d %I64d ",x1,y1);
			y2=(y2%abs(a/d)+abs(a/d))%abs(a/d);
			x2=(c-y2*b)/a;
			printf("%I64d %I64d\n",x2,y2);
		}
	}
	return 0;
}
我们来个孙子定理完整版。
可能现在还来不起。。。我们就先假设mi 两两互质吧。
Input
第一行一个整数T,表示需要求解的方程组数。
接下来T 个方程组,对于每个方程组:
第1 行一个整数n,表示方程组对应的方程个数。
接下来n 行,第i 行两个数:ai mi 表示第i 个方程:
x ai (mod mi)
Output

对于每个方程:输出最小非负整数解。

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
long long t,n;
vector<long long> vm;
vector<long long> va;
long long exgcd(long long a,long long b,long long &x,long long &y)
{
	if (b==0)
	{
		x=1;
		y=0;
		return a;
	}
	long long x1,y1;
	long long cd=exgcd(b,a%b,x1,y1);
	x=y1;
	y=x1-(a/b)*y1;
	return cd;
}
long long ins(long long num,long long mod)
{
	long long x,y;
	exgcd(num,mod,x,y);
	return (x%mod+mod)%mod;
}
long long crt(vector<long long> va,vector<long long> vm)
{
	long long x=0;
	long long len=(long long)va.size();
	long long M=1;
	for (int i=0;i<len;i++)
	   M*=vm[i];
	for (int i=0;i<len;i++){
		long long ci=M/vm[i];
		long long ny=ins(ci,vm[i]);
		x=(x+va[i]*ny%M*ci%M)%M;
	}
	return x;   
}
int main()
{
	freopen("crt.in","r",stdin);
	freopen("crt.out","w",stdout);
	scanf("%d",&t);
	while (t--)
	{
		scanf("%d",&n);
		va.clear();
		vm.clear();
		for (int i=1;i<=n;i++)
		{
			long long aa,mm;
			scanf("%I64d%I64d",&aa,&mm);
			
			va.push_back(aa);
			vm.push_back(mm);
		}printf("%I64d\n",crt(va,vm));
	}
	return 0;
}
我们来个递推精简版。求下面数列的第n 项:
f(0) = a0; f(1) = a1; f(2) = a2
f(n) = bf(n

猜你喜欢

转载自blog.csdn.net/beloved_rancy/article/details/79319144