【矩阵快速幂】[2016"百度之星" - 初赛(Astar Round2A)]All X

题目

Problem Description
F(x,m) 代表一个全是由数字x组成的m位数字。请计算,以下式子是否成立:

F(x,m)modkc

Input
第一行一个整数T,表示T组数据。
每组测试数据占一行,包含四个数字 x,m,k,c

1x9

1m1010

0c<k10,000

Output
对于每组数据,输出两行:
第一行输出:”Case #i:”。i代表第i组测试数据。
第二行输出“ Yes ” 或者 “ No ”,代表四个数字,是否能够满足题目中给的公式。

Sample Input
3
1 3 5 2
1 3 5 1
3 5 99 69

Sample Output
Case #1:
No
Case #2:
Yes
Case #3:
Yes

Hint

对于第一组测试数据:111 mod 5 = 1,公式不成立,所以答案是” No ”,而第二组测试数据中满足如上公式,所以答案是 “ Yes ”。

分析

F(x,m)=F(x,m1)10+m

F(x,0)=0

这样一个递推式显然可以用矩阵加速
[F(x,m),m]=[F(x,m1),m][10,01,1]

代码

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#define MAXN 50000
using namespace std;
typedef pair<int,int>pii;
typedef pair<int,pii>pip;
long long T,x,m,k,c;
template<class T>
void Read(T &x){
    char c;
    bool f=0;
    while(c=getchar(),c!=EOF){
        if(c=='-')
            f=1;
        if(c>='0'&&c<='9'){
            x=c-'0';
            while(c=getchar(),c>='0'&&c<='9')
                x=x*10+c-'0';
            ungetc(c,stdin);
            if(f)
                x=-x;
            return;
        }
    }
}
struct matrix{
    int a[2][2];
    matrix(int ){
        memset(a,0,sizeof a);
        for(int i=0;i<2;i++)
            a[i][i]=1;
    }
    matrix(){
        memset(a,0,sizeof a);
    }
    matrix operator*(const matrix &b)const{
        matrix c;
        int i,j,l;
        for(i=0;i<2;i++)
            for(j=0;j<2;j++)
                for(l=0;l<2;l++)
                    c.a[i][j]=(c.a[i][j]+a[i][l]*b.a[l][j])%k;
        return c;
    }
    void operator*=(const matrix &b){
        *this=*this*b;
    }
}a;
matrix quick_pow(matrix c,long long b){
    matrix ret(m),a(c);
    while(b){
        if(b&1)
            ret*=a;
        a*=a;
        b>>=1;
    }
    return ret;
}
void read(){
    Read(x),Read(m),Read(k),Read(c);
}
void solve(){
    a.a[0][0]=10,a.a[0][1]=0;
    a.a[1][0]=1,a.a[1][1]=1;
    a=quick_pow(a,m);
    if(x*a.a[1][0]%k==c)
        puts("Yes");
    else
        puts("No");
}
int main()
{
    Read(T);
    int cnt=0;
    while(T--){
        printf("Case #%d:\n",++cnt);
        read();
        solve();
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值