POJ - 2115 C Looooops(扩展欧几里德求解模线性方程(线性同余方程))
2016-03-09 21:43
501 查看
d.对于这个循环,
给出A,B,C,求在k位存储系统下的循环次数。
例如k=4时,变量variable则只在0~15之间循环变化。
s.扩展欧几里德求解模线性方程(线性同余方程)。
设循环次数为x,
1.(A+C*x)mod 2^k=B. --> C*x=B-A(mod 2^k). (怎么变来的?)
2.C*x=B-A(mod 2^k). --> C*x+(2^k)*y=B-A.
扩展欧几里德求:C*x+(2^k)*y=gcd(C,2^k)=d.(原式:a*x+b*y=gcd(a,b)=d,以下a代表C,b代表2^k。)
如果(B-A)mod d==0(也就是(B-A)的值可以整除d,貌似表示为d|(B-A)?),则原方程C*x+(2^k)*y=B-A.的解为x'=x*((B-A)/d)。
3.利用周期性变化,求出最小的非负整数解为x''=(x'%(b/d)+(b/d))%(b/d).
因为:如果C*x+(2^k)*y=B-A.的一组整数解为(x1,y1),则它的任意整数解为(x1+k*(b/d)),y1-k*(a/d)).(k取任意整数)
(1)若x1为负的,取最大的非正值:x1=x1%(b/d).;若x1为正值,以下两步无影响;
(2)取正:x1=x1+(b/d).
(3)防止(1)中的x1=0,那么第(2)步x1变为(b/d),所以x1=x1%(b/d).
为什么b/gcd(a,b),a/gcd(a,b)分别为x,y的解的最小间距?
解:假设c为x的解的最小间距,此时d为y的解的间距,所以x=x0+c*t,y=y0-d*t(x0,y0为一组特解,t为任意整数)
带入方程得:a*x0+a*c*t+b*y0-b*d*t=n,因为a*x0+b*y0=n,所以a*c*t-b*d*t=0,t不等于0时,a*c=b*d
因为a,b,c,d都为正整数,所以用最小的c,d,使得等式成立,ac,bd就应该等于a,b的最小公倍数a*b/gcd(a,b),
所以c=b/gcd(a,b),d就等于a/gcd(a,b)。
所以,若最后所求解要求x为最小整数,那么x=(x0%(b/gcd(a,b))+b/gcd(a,b))%(b/gcd(a,b))即为x的最小整数解。
x0%(b/gcd(a,b))使解落到区间-b/gcd(a,b)~b/gcd(a,b),再加上b/gcd(a,b)使解在区间0~2*b/gcd(a,b),
再模上b/gcd(a,b),则得到最小整数解(注意b/gcd(a,b)为解的最小距离,重要)
c.
View Code
ps:题解可以参考这个:http://www.cnblogs.com/My-Sunshine/p/4828600.html 当时就是看这个才懂的
for (variable = A; variable != B; variable += C) statement;
给出A,B,C,求在k位存储系统下的循环次数。
例如k=4时,变量variable则只在0~15之间循环变化。
s.扩展欧几里德求解模线性方程(线性同余方程)。
设循环次数为x,
1.(A+C*x)mod 2^k=B. --> C*x=B-A(mod 2^k). (怎么变来的?)
2.C*x=B-A(mod 2^k). --> C*x+(2^k)*y=B-A.
扩展欧几里德求:C*x+(2^k)*y=gcd(C,2^k)=d.(原式:a*x+b*y=gcd(a,b)=d,以下a代表C,b代表2^k。)
如果(B-A)mod d==0(也就是(B-A)的值可以整除d,貌似表示为d|(B-A)?),则原方程C*x+(2^k)*y=B-A.的解为x'=x*((B-A)/d)。
3.利用周期性变化,求出最小的非负整数解为x''=(x'%(b/d)+(b/d))%(b/d).
因为:如果C*x+(2^k)*y=B-A.的一组整数解为(x1,y1),则它的任意整数解为(x1+k*(b/d)),y1-k*(a/d)).(k取任意整数)
(1)若x1为负的,取最大的非正值:x1=x1%(b/d).;若x1为正值,以下两步无影响;
(2)取正:x1=x1+(b/d).
(3)防止(1)中的x1=0,那么第(2)步x1变为(b/d),所以x1=x1%(b/d).
为什么b/gcd(a,b),a/gcd(a,b)分别为x,y的解的最小间距?
解:假设c为x的解的最小间距,此时d为y的解的间距,所以x=x0+c*t,y=y0-d*t(x0,y0为一组特解,t为任意整数)
带入方程得:a*x0+a*c*t+b*y0-b*d*t=n,因为a*x0+b*y0=n,所以a*c*t-b*d*t=0,t不等于0时,a*c=b*d
因为a,b,c,d都为正整数,所以用最小的c,d,使得等式成立,ac,bd就应该等于a,b的最小公倍数a*b/gcd(a,b),
所以c=b/gcd(a,b),d就等于a/gcd(a,b)。
所以,若最后所求解要求x为最小整数,那么x=(x0%(b/gcd(a,b))+b/gcd(a,b))%(b/gcd(a,b))即为x的最小整数解。
x0%(b/gcd(a,b))使解落到区间-b/gcd(a,b)~b/gcd(a,b),再加上b/gcd(a,b)使解在区间0~2*b/gcd(a,b),
再模上b/gcd(a,b),则得到最小整数解(注意b/gcd(a,b)为解的最小距离,重要)
c.
#include<iostream> #include<stdio.h> using namespace std; //返回d=gcd(a,b);和对应于等式ax+by=d中的x,y long long extend_gcd(long long a,long long b,long long &x,long long &y){ if(a==0&&b==0)return -1;//无最大公约数 if(b==0){x=1;y=0;return a;} long long d=extend_gcd(b,a%b,y,x); y-=a/b*x; return d; } //求逆元 //ax=1(mod n) long long mod_reverse(long long a,long long n){ long long x,y; long long d=extend_gcd(a,n,x,y); if(d==1)return (x%n+n)%n; else return -1; } int main(){ long long A,B,C,k; long long a,b,x,y; long long d; while(~scanf("%lld%lld%lld%lld",&A,&B,&C,&k)){ if(A==0&&B==0&&C==0&&k==0)break; a=C; b=((long long)1)<<k; d=extend_gcd(a,b,x,y); if((B-A)%d==0){ x=(x*((B-A)/d))%b; x=(x%(b/d)+(b/d))%(b/d); printf("%lld\n",x); } else{ printf("FOREVER\n"); } } return 0; }
View Code
ps:题解可以参考这个:http://www.cnblogs.com/My-Sunshine/p/4828600.html 当时就是看这个才懂的
相关文章推荐
- Linux系统信号学习笔记
- eclipse部署web项目至本地的tomcat但在webapps中找不到
- 每天一个linux命令(18):locate 命令
- HDU 3853 LOOPS(概率DP简单题)
- 小菜鸟装VM之后装linux
- linux基础命令
- zabbix-agent windows linux客户端安装
- Linux 驱动开发之内核模块开发(四)—— 符号表的导出
- mysql高可用方案MHA介绍
- 【OpenGL】 001 Open a window
- 通过 git bash 配置和使用 github
- CentOS 6.5结合busybox完成自制Linux系统及远程登录和nginx安装测试
- CentOS 6.5结合busybox完成自制Linux系统及远程登录和nginx安装测试
- Apache Mahout 简介 通过可伸缩、商业友好的机器学习来构建智能应用程序
- 在CentOS 6.5里添加一块硬盘,分区并格式化后,挂载到/data下
- zjnu1709 UZASTOPNI (bitset,树形dp)
- DropDownMenu下拉筛选排序Menu
- linux启动流程
- Hadoop Distributed File System 简介
- 使用 Linux 和 Hadoop 进行分布式计算