[ARC020C] A mod B Problem 解题记录

[ARC020C] A mod B Problem 解题记录


看到题解区没有用矩乘写的,所以我来水一发

题意简述

现在有一个很大的整数,由  N N N 个部分组成,第  i i i 个部分由  a i a_i ai​ 重复  l i l_i li​ 次得到。
求大整数模  B B B 的值。


题目分析

如果不考虑取模的话,那么这个数字 a n s ans ans 可以写为
a 1 a 1 ⋯ a 1 ⏟ l 1 个 a 2 a 2 ⋯ a 2 ⏟ l 2 个 a 3 a 3 ⋯ a 3 ⏟ l 3 个 ⋯ a n a n ⋯ a n ⏟ l n 个 ‾ \overline{\underbrace{a_1 a_1 \cdots a_1} _{l_1个}\underbrace{a_2 a_2 \cdots a_2} _{l_2个}\underbrace{a_3 a_3 \cdots a_3} _{l_3个} \cdots \underbrace{a_n a_n \cdots a_n} _{l_n个}} l1 a1a1a1l2 a2a2a2l3 a3a3a3ln ananan
如果从 1 1 1 开始遍历,对于每个 i i i a n s ans ans 就会乘上 a i a_i ai 的位数再加上 a i a_i ai,重复 l i l_i li 次。
形式化的来讲, a n s → a n s × 1 0 log ⁡ a i + 1 + a i ans \to ans \times 10^{\log a_i + 1} + a_i ansans×10logai+1+ai,重复 l i l_i li 次。
对于这种转移柿子,我们可以自然而然地想到矩乘。
考虑初始矩阵。需要记录 a n s ans ans,并且每次要加上 a i a_i ai,所以可以设初始矩阵为
[ a n s a i ] \begin{bmatrix} ans & a_i \end{bmatrix} [ansai]
每次 a n s ans ans 变为 a n s × 1 0 ( log ⁡ a i + 1 ) + a i ans \times 10^{(\log a_i + 1)} + a_i ans×10(logai+1)+ai,重复 l i l_i li 次,所以需要转移矩阵为
[ 1 0 log ⁡ a i + 1 0 1 1 ] l i \begin{bmatrix} 10^{\log a_i+1}& 0\\ 1&1 \end{bmatrix}^{l_i} [10logai+1101]li
遍历 1 ∼ n 1 \sim n 1n,每次乘上转移矩阵,最终值为初始矩阵的 a n s ans ans
注意:本题为早期 Atcoder 结尾需要输出换行。


AC Code
#include<bits/stdc++.h>
#define arrout(a,n) rep(i,1,n)std::cout<<a[i]<<" "
#define arrin(a,n) rep(i,1,n)std::read()
#define rep(i,x,n) for(int i=x;i<=n;i++)
#define dep(i,x,n) for(int i=x;i>=n;i--)
#define erg(i,x) for(int i=head[x];i;i=e[i].nex)
#define dbg(x) std::cout<<#x<<":"<<x<<" "
#define mem(a,x) memset(a,x,sizeof a)
#define all(x) x.begin(),x.end()
#define arrall(a,n) a+1,a+1+n
#define PII std::pair<int,int>
#define m_p std::make_pair
#define u_b upper_bound
#define l_b lower_bound
#define p_b push_back
#define CD const double
#define CI const int
#define int long long
#define il inline
#define ss second
#define ff first
#define itn int
int read() {
    char ch=getchar();
    int r=0,w=1;
    while(ch<'0'||ch>'9') w=ch=='-'?-1:w,ch=getchar();
    while(ch>='0'&&ch<='9') r=r*10+ch-'0',ch=getchar();
    return r*w;
}
CI N=1e4+5;
int n,a[N],l[N],mod;
struct matrix {
    int mat[2][2];
    matrix() {
        mem(mat,0);
    }
    matrix operator*(const matrix& b)const {
        matrix ans;
        rep(i,0,1) {
            rep(j,0,1) {
                rep(k,0,1) {
                    ans.mat[i][j]=(ans.mat[i][j]+mat[i][k]*b.mat[k][j]%mod)%mod;
                }
            }
        }
        return ans;
    }
    matrix operator^(int& b)const {
        matrix ans,a=*this;
        ans.mat[0][0]=ans.mat[1][1]=1;
        while(b) {
            if(b&1) {
                ans=ans*a;
            }
            a=a*a;
            b>>=1;
        }
        return ans;
    }
}g,t;
int32_t main() {
    n=read();
    rep(i,1,n) {
        a[i]=read();
        l[i]=read();
    }
    mod=read();
    rep(i,1,n) {
        g.mat[0][1]=a[i];
        t.mat[0][0]=(int)pow(10,(int)log10(a[i])+1)%mod;
        t.mat[1][0]=1;
        t.mat[1][1]=1;
        g=g*(t^l[i]);
    }
    std::cout<<g.mat[0][0]%mod<<"\n";
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值