单变量线性同余方程的C++实现

在这里要注意一点的就是乘法逆的求法:

求a关于n的乘法逆的方法就是利用扩展的欧几里得算法求解:

s * n + a * t = 1 (gcd(n,a) = 1才存在乘法逆)

实现代码如下:

int gcd(int x,int y){  
    return y == 0 ? x : gcd(y,x%y);   
}   
void exEuclidean(int a,int b,int &s,int &t){  
    int r1 = a, r2 = b , s1 = 1, s2 = 0, t1 = 0, t2 = 1;//初始化  
    int q,r;   
    while(r2 > 0)  
    {  
        q = r1 / r2;  
  
        r = r1 - q * r2; //也就是r = r1%r2;  
        r1 = r2;  
        r2 = r;  
  
        s = s1 - q * s2;  
        s1 = s2;  
        s2 = s;  
        
        t = t1 - q * t2;  
        t1 = t2;  
        t2 = t;   
    }  
    //gcd(a,b) = r1;   
    s = s1;   
    t = t1;  
}  
int main()
{
	int a,n,b;
	printf("请依次输入ax %% n = b方程中的系数 a , n ,b!\n");
	//其实就是ax = kn + b ,也就是 ax + nk = b-------线性丢番图方程 
	scanf("%d %d %d",&a,&n,&b);
	int gcd_a_n = gcd(a,n);
	if(b%gcd_a_n != 0){
		//根据线性丢番图方程 ax + by = c中如果gcd(a,b)不能整除c的话,无解 
		printf("gcd(a,n)不能整出b,该方程无解\n");
	}
	else{ //有解 
		//(1)除以gcd_a_n,简化方程 
		a /= gcd_a_n;
		n /= gcd_a_n;
		b /= gcd_a_n; 
		
		//(2)乘以a的乘法逆,找出方程特解x0
		//利用扩展的欧几里得算法求 n * s + a * t = 1(注意:1是n和a的gcd)   
        int s,t;  
        exEuclidean(n,a,s,t); //因为传引用,s和t得到解了 
        int a_ = (t >= 0) ? (t % n) : ((t-t*n)%n); //乘法逆就是t映射于n的值 
        int x0 = (b*a_)%n;
        printf("特解是%d\n",x0);
		 
		//(3)得到所有的通解 
		printf("通解是 x0 + k * %d , 0 <= k < %d\n",n,gcd_a_n);
		printf("所有的通解为:\n");
		vector<int> ans;
		for(int i = 0 ; i < gcd_a_n; i++){
			ans.push_back(x0 + i * n);
			printf("%d ",ans[i]);
		}
		printf("\n");
	}
}

运行结果如下:


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 线性回归的目的是找到一条能尽量好地拟合数据的直线。其中,回归系数b和截距a是要求的参数。 线性回归的数学方程为: y = bx + a 其中,y是预测值,b是回归系数,x是自变量,a是截距。 算法流程如下: 1. 先求出所有数据的均值,分别记作 x̄ 和 ȳ。 2. 利用公式 b = Σ((x - x̄)(y - ȳ)) / Σ((x - x̄)^2) 求出回归系数b。 3. 利用公式 a = ȳ - b * x̄ 求出截距a。 算法实现的代码示例如下: #include <stdio.h> #include <stdlib.h> #include <math.h> #define N 100 int main() { int i; double x[N], y[N]; //存储自变量和因变量的数组 double x_mean = 0, y_mean = 0; //存储自变量和因变量的均值 double b, a; //存储回归系数和截距 //输入自变量和因变量的值 for (i = 0; i < N; i++) { scanf("%lf%lf", &x[i], &y[i]); x_mean += x[i]; y_mean += y[i]; } x_mean /= N; y_mean /= N; //计算回归系数b double numerator = 0, denominator = 0; //分子和分母 for (i = 0; i < N; i++) { numerator += (x[i] - x_mean) * (y[i] - y_mean); denominator += (x[i] - x_mean) * (x[i] - x_mean); } b = numerator / denominator; //计算截距 ### 回答2: 线性回归是一种用于建立自变量和因变量之间关系的成熟算法。通过使用C语言来实现线性回归方程的算法,我们需要以下步骤: 1. 导入所需的C库和头文件:我们需要包含stdio.h和math.h头文件,以便使用数学函数和输入输出函数。 2. 定义训练数据集:创建两个数组,一个用于存储自变量的值,另一个用于存储相应的因变量的值。 3. 计算平均值:使用循环遍历自变量数组,计算其平均值。 4. 计算方差和协方差:使用循环遍历自变量和因变量数组,计算它们之间的方差和协方差。 5. 计算回归系数:使用公式\( b = \frac{Cov(x, y)}{Var(x)} \)计算回归系数b。 6. 计算截距:使用公式\( a = \bar{y} - b\bar{x} \)计算回归方程的截距。 7. 输出回归方程:打印回归方程的系数和截距。 8. 进行预测:根据回归方程,使用用户提供的输入值进行预测。 9. 输出预测结果:打印预测值。 接下来,我将用C代码演示如何实现上述算法: ```c #include <stdio.h> #include <math.h> int main() { int n = 5; //数据集大小 double x[] = {1, 2, 3, 4, 5}; //自变量数组 double y[] = {2, 4, 6, 8, 10}; //因变量数组 //计算平均值 double x_mean = 0, y_mean = 0; for(int i = 0; i < n; i++){ x_mean += x[i]; y_mean += y[i]; } x_mean /= n; y_mean /= n; //计算方差和协方差 double var_x = 0, cov_xy = 0; for(int i = 0; i < n; i++){ var_x += pow(x[i] - x_mean, 2); cov_xy += (x[i] - x_mean) * (y[i] - y_mean); } var_x /= n; cov_xy /= n; //计算回归系数和截距 double b = cov_xy / var_x; double a = y_mean - b * x_mean; //输出回归方程 printf("回归方程: y = %.2fx + %.2f\n", b, a); //进行预测 double input = 6; double prediction = b * input + a; //输出预测结果 printf("预测值: %.2f\n", prediction); return 0; } ``` 以上就是使用C语言实现线性回归方程的算法的步骤和示例代码。 ### 回答3: 线性回归是一种用于建立变量之间线性关系的统计分析方法,用于预测因变量和自变量之间关系的强度和方向。我将用C语言来实现线性回归方程的算法。 首先,我们需要准备一组样本数据,包括自变量和因变量。假设我们有n个样本数据,自变量用X表示[x1, x2, ..., xn],因变量用Y表示[y1, y2, ..., yn]。 接下来,我们需要计算自变量和因变量的平均值,记为Xmean和Ymean。然后,计算自变量和因变量的标准差,分别记为Xstd和Ystd。 然后,我们需要计算自变量和因变量的协方差,记为CovXY。协方差可以通过以下公式计算: `CovXY = Σ((xi - Xmean)*(yi - Ymean)) / (n-1)` 接着,我们可以计算线性回归方程的斜率b和截距a。斜率可以通过以下公式计算: `b = CovXY / Xstd^2` 截距可以通过以下公式计算: `a = Ymean - b * Xmean` 最后,我们可以得到线性回归方程的表达式: `Y = a + b * X` 以上就是用C语言实现线性回归方程的算法。通过计算自变量和因变量的平均值、标准差和协方差,我们可以得到线性回归方程的斜率和截距,从而进行预测和分析。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值