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:\n",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\n");
        else printf("No\n");
    }
    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:\n",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\n"); else printf("No\n");
    }
    return 0;
}</span>



posted @ 2016-05-24 16:26  HARD_UNDERSTAND  阅读(219)  评论(0编辑  收藏  举报