• 同余和矩阵乘法


    同余:扩展欧几里得算法

    已知GCD(a,b)=d

    可求a*x+b*y=d x和y是要求的

    9c745219f158407c9c555fac31a50003.png

    大致的问题 a*x同余b(mod c)等价于a*x+c*y=b

    模板

    1. int exgcd(int a,int b,int &x,int &y)//拓展欧几里得求ax+by=d的方程
    2. {
    3. if(!b)
    4. {
    5. x=1,y=0;
    6. return a;
    7. }
    8. int d=exgcd(b,a%b,y,x);
    9. y-=a/b*x;
    10. return d;
    11. }

    1.同余方程

    203. 同余方程 - AcWing题库

    ax=1(mod b)转化为ax+by=1,则直接用拓展欧几里得算法即可求x,y,最小x解为x0%b

    1. #include
    2. using namespace std;
    3. typedef long long ll;
    4. int exgcd(int a,int b,int &x,int &y)
    5. {
    6. if(!b)
    7. {
    8. x=1,y=0;
    9. return a;
    10. }
    11. int d=exgcd(b,a%b,y,x);
    12. y-=a/b*x;
    13. return d;
    14. }
    15. int main()
    16. {
    17. int a,b;
    18. cin>>a>>b;
    19. int x,y;
    20. exgcd(a,b,x,y);
    21. cout<<(x%b+b)%b<
    22. return 0;
    23. }

    2.青蛙的约会

    222. 青蛙的约会 - AcWing题库

    然后用扩展欧几里得算法就可以得到任意一组解 然后是求x的最小解 并且x是不等于0 的

    则最小的x为x0%(l/d)

    1. #include
    2. using namespace std;
    3. typedef long long ll;
    4. ll exgcd(ll a,ll b,ll &x,ll &y)//拓展欧几里得求ax+by=d的方程
    5. {
    6. if(!b)
    7. {
    8. x=1,y=0;
    9. return a;
    10. }
    11. ll d=exgcd(b,a%b,y,x);
    12. y-=a/b*x;
    13. return d;
    14. }
    15. int main()
    16. {
    17. ll a,b,n,m,l;
    18. cin>>a>>b>>m>>n>>l;
    19. ll x,y;
    20. ll d=exgcd(m-n,l,x,y);
    21. if((b-a)%d) puts("Impossible");//假如b-a不是公约数
    22. else
    23. {
    24. x*=(b-a)/d;//将x扩大相应的倍数
    25. ll t=abs(l/d);//将d除过来,让右边为1,才能用t0%b为最小这个定里
    26. cout<<((x%t)+t)%t<//输出最小结果
    27. }
    28. return 0;
    29. }

     3.最幸运的数字

    202. 最幸运的数字 - AcWing题库

    bb5ec626284c4d3f9a19b004f938e3ae.png

    1. #include
    2. using namespace std;
    3. typedef long long ll;
    4. ll get_euler(ll c)//获取一个数的欧拉数
    5. {
    6. ll res=c;
    7. for(ll i=2;i<=c/i;i++)
    8. if(c%i==0)
    9. {
    10. while(c%i==0) c/=i;
    11. res=res/i*(i-1);//套欧拉函数的公式
    12. }
    13. if(c>1) res=res/c*(c-1);
    14. return res;
    15. }
    16. ll qmul(ll a,ll k,ll p)//龟速乘
    17. {
    18. ll res=0;
    19. while(k)
    20. {
    21. if(k&1) res=(res+a)%p;
    22. a=(a+a)%p;
    23. k>>=1;
    24. }
    25. return res;
    26. }
    27. ll qmi(ll a,ll k,ll p)//快速幂
    28. {
    29. ll res=1;
    30. while(k)
    31. {
    32. //res=(__int128_t)res*a%p也行
    33. if(k&1) res=qmul(res,a,p);//因为乘法会爆ll,所以用龟速乘
    34. //a=(__int128_t)a*a%p也行
    35. a=qmul(a,a,p);//因为乘法会爆ll,所以用龟速乘
    36. k>>=1;
    37. }
    38. return res;
    39. }
    40. int main()
    41. {
    42. int T=1;
    43. ll l;
    44. while(cin>>l,l)
    45. {
    46. int d=1;
    47. while(l%(d*2)==0&&d*2<=8) d*=2;
    48. ll c=9*l/d;//获取要整除的C
    49. ll phi=get_euler(c);//获取他的欧拉数
    50. ll res=1e18;
    51. if(c%2==0||c%5==0) res=0;//假如跟10不互质,则没答案
    52. for(ll d=1;d*d<=phi;d++)//枚举欧拉数的所有约数
    53. if(phi%d==0)//假如这个是约数了
    54. {
    55. if(qmi(10,d,c)==1) res=min(res,d);//判断符不符合条件
    56. if(qmi(10,phi/d,c)==1) res=min(res,phi/d);//判断符不符合条件
    57. }
    58. printf("Case %d: %lld\n",T++,res);
    59. }
    60. return 0;
    61. }

     4.曹冲养猪

    信息学奥赛一本通(C++版)在线评测系统

    中国剩余定理

    15065e552653434580794e16c3627044.png

    1. #include
    2. using namespace std;
    3. typedef long long ll;
    4. const int N=11;
    5. int A[N],B[N];
    6. int n;
    7. ll exgcd(ll a,ll b,ll &x,ll &y)//用扩展欧几里得求逆元
    8. {
    9. if(!b)
    10. {
    11. x=1,y=0;
    12. return a;
    13. }
    14. ll d=exgcd(b,a%b,y,x);
    15. y-=a/b*x;
    16. return d;
    17. }
    18. int main()
    19. {
    20. cin>>n;
    21. ll M=1,res=0;
    22. for(int i=0;i
    23. {
    24. scanf("%d%d",&A[i],&B[i]);
    25. M*=A[i];//处理所有的乘积
    26. }
    27. for(int i=0;i
    28. {
    29. ll Mi=M/A[i];//获取Mi
    30. ll ti,x;
    31. exgcd(Mi,A[i],ti,x);//求Mi的逆元ti
    32. res+=B[i]*Mi*ti;//图片中有讲答案加上即可
    33. }
    34. cout<<((res%M)+M)%M<//输出正的模余数
    35. return 0;
    36. }

     矩阵乘法

    1.斐波那契前 n 项和

    1303. 斐波那契前 n 项和 - AcWing题库

    f4a53426c1c8427ba212ecb272ab2ad3.png

    035814d54328478695b1134a6aec02ee.png

    这里也可以定义为Fn=[fn-1,fn]

    详细 

    1. #include
    2. using namespace std;
    3. typedef long long ll;
    4. const int N=3;
    5. int n,m;
    6. void mul(int c[],int a[],int b[][N])
    7. {
    8. int temp[N]={0};
    9. for(int i=0;i//矩阵乘法
    10. for(int j=0;j
    11. temp[i]=(temp[i]+(ll)a[j]*b[j][i])%m;
    12. memcpy(c,temp,sizeof temp);
    13. }
    14. void mul(int c[][N],int a[][N],int b[][N])
    15. {
    16. int temp[N][N]={0};
    17. for(int i=0;i//矩阵乘法
    18. for(int j=0;j
    19. for(int k=0;k
    20. temp[i][j]=(temp[i][j]+(ll)a[i][k]*b[k][j])%m;
    21. memcpy(c,temp,sizeof temp);
    22. }
    23. int main()
    24. {
    25. cin>>n>>m;
    26. int f1[N]={1,1,1};//f1为1时的矩阵
    27. int a[N][N]={
    28. {0,1,0},
    29. {1,1,1},
    30. {0,0,1}
    31. };//a矩阵
    32. n--;//求Fn-1
    33. while(n)
    34. {
    35. if(n&1) mul(f1,f1,a);//res=res*a
    36. mul(a,a,a);//a=a*a;
    37. n>>=1;
    38. }
    39. cout<2]<//输出Fn-1的中的f(n-1)+1=fn
    40. return 0;
    41. }

  • 相关阅读:
    Sybase连接详解
    一些现代 Javascript 技巧
    离开二线城市石家庄(勉强算二线吧)去北漂,入职外包测试岗一个月想辞职了~
    出血性脑卒中临床智能诊疗建模
    队列的基本操作(数据结构)
    【ASE+python学习】-批量识别石墨烯团簇结构中的吡啶氮,并删除与其相连的氢
    【电商运营】社交媒体营销策略该如何制定?
    同轴电缆技术参数(一)
    【C语言初阶】 一文详解分支语句 if
    入门力扣自学笔记192 C++ (题目编号:1620)
  • 原文地址:https://blog.csdn.net/lee_14141/article/details/127649788