zoukankan      html  css  js  c++  java
  • hdu 5690 矩阵快速幂/循环节

    题意:求m个x组成的数模k是否等于c

    m<=10^10,k<=10000

    分析:

    百度之星初赛第一场的题,这题我A了,我的做法是:把m%k位数直接模拟取模操作,因为k<=10000,所以复杂度并不高。虽然A了,但是后来想了想,这种方法是错的,比如样例:1 13 13 1,如果按照我的做法,13%13=0,0个1=0 0!=1 所以输出No。但是实际上应该输出Yes。可能是数据太水,被我碰巧过了吧。

    看了大神的题解:http://blog.csdn.net/u012288458/article/details/51472661

    原来这题是用快速幂来做,自己还是太菜了,做题不够啊!

    第一种,裸的矩阵乘法,构造矩阵

    {f(x,i),x}*{10 0}={f(x,i+1),x}

                  {1  1}

    复杂度O(Tlog m)


    <span style="font-size:14px;">#include<cstdio>
    #include<cstring>
    #include<vector>
    #include<queue>
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    const int N=100000+9;
    int mod;
    struct Mat
    {
        int x,y;
        int m[3][3];
        Mat operator*(Mat b)
        {
            Mat ans;
            memset(ans.m,0,sizeof(ans.m));
            ans.x=x;ans.y=b.y;
            for(int i=1;i<=ans.x;i++)
                for(int j=1;j<=ans.y;j++)
                for(int k=1;k<=y;k++)
                ans.m[i][j]=(ans.m[i][j]+m[i][k]*b.m[k][j]%mod)%mod;
            return ans;
        }
    };
    int main()
    {
        int T;scanf("%d",&T);
        int x,k,cc;
        ll m;
        for(int cas=1;cas<=T;cas++){
            printf("Case #%d:
    ",cas);
            scanf("%d%lld%d%d",&x,&m,&k,&cc);
            mod=k;
            Mat a,b,c;
            a.x=1,a.y=2,a.m[1][1]=0,a.m[1][2]=x;
            b.x=b.y=2,b.m[1][1]=10,b.m[1][2]=0,b.m[2][1]=b.m[2][2]=1;
            c.x=c.y=2;c.m[1][1]=c.m[2][2]=1;c.m[1][2]=c.m[2][1]=0;
            for(;m;m>>=1){
                if(m&1)c=c*b;
                b=b*b;
            }
            a=a*c;
            if(a.m[1][1]==cc)printf("Yes
    ");
            else printf("No
    ");
        }
        return 0;
    }</span>

    还可以用循环节来做,因为是模k,取模后最多有k个数,循环节显然小于K

    所以时间复杂度是O(k)

    <span style="font-size:14px;">#include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<cmath>
    #include<iostream>
    #include<algorithm>
    
    using namespace std;
    
    int T;
    int x,mod,c;
    int dep[10010];
    long long m;
    
    int main()
    {
        scanf("%d",&T);
        for (int j=1;j<=T;j++)
        {
            scanf("%d%I64d%d%d",&x,&m,&mod,&c);
            printf("Case #%d:
    ",j);
            memset(dep,0,sizeof(dep));
            int now=0,cnt=0;
            for (;m>0;)
            {
                now=(now*10+x)%mod;cnt++;m--;
                if (!dep[now]) dep[now]=cnt;
                else m%=(long long)(cnt-dep[now]);
            }
            if (now==c) printf("Yes
    "); else printf("No
    ");
        }
        return 0;
    }</span>



  • 相关阅读:
    re模块 与正则表达式之间的关系 一.....
    计算机硬件组成
    随便
    linux crontab定时
    linux shell命令记录
    tomcat意外退出 A valid shutdown command was received via the shutdown port. Stopping the Server instance
    mongodb设置用户
    mongodb的mongo.conf文件 启动参数
    mysql设置不区分表名大小写
    mongodb报Write failed with error code 17280 and error message 'WiredTigerIndex::insert: key too large
  • 原文地址:https://www.cnblogs.com/01world/p/5651202.html
Copyright © 2011-2022 走看看