矩阵乘法专题4——bzoj 2326 [HNOI2011] 数学作业 题解

转载请注明:http://blog.csdn.net/jiangshibiao/article/details/24963747

【原题】

2326: [HNOI2011]数学作业

Time Limit: 10 Sec  Memory Limit: 128 MB

Submit: 853  Solved: 473

[Submit][Status]

Description

【分析】我们按数字的位数来划分。对于K位数,我们就可以专门设计一个矩阵来计算。

然后就是注意细节了。

【代码】

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
struct matrix
{
  ll p[4][4];int n,m;
  matrix(){memset(p,0,sizeof(p));}
}res,a;
ll MOD,n,chen,i,ans;
matrix operator * (matrix a,matrix b)
  {
    matrix c;c.n=a.n;c.m=a.m;
    for (int i=1;i<=a.n;i++)
      for (int j=1;j<=b.m;j++)
        for (int k=1;k<=a.m;k++)
          c.p[i][j]=(c.p[i][j]+1ll*a.p[i][k]*b.p[k][j])%MOD;
    return c;
  }
void make_matrix()
{
  a.p[1][2]=a.p[1][3]=a.p[2][3]=0ll;
  a.p[2][1]=a.p[2][2]=a.p[3][1]=a.p[3][2]=a.p[3][3]=1ll;
  a.p[1][1]=chen%MOD;a.n=3;a.m=3;
  res.p[1][2]=(chen/10-1ll)%MOD;res.p[1][3]=1ll;
  res.n=1;res.m=3;
}
void quick(ll b)
{
  bool flag=true;
  while (b)
  {
    if (b&1ll) res=res*a;
    b=b/2ll;a=a*a;
  }
}
int main()
{
  scanf("%lld%lld",&n,&MOD);
  res.p[1][1]=0ll;chen=1ll;
  for (i=1;i<=18;i++)
  {
    chen*=10ll;
    make_matrix();
    quick((chen<=n)?(chen/10*9ll):(n-chen/10+1ll));
    if (chen>n) break;
  }
  printf("%lld",res.p[1][1]);
  return 0;
}

矩阵乘法专题4——bzoj 2326 [HNOI2011] 数学作业 题解,布布扣,bubuko.com

时间: 2024-08-02 15:14:13

矩阵乘法专题4——bzoj 2326 [HNOI2011] 数学作业 题解的相关文章

矩阵乘法专题3——bzoj 1898 [Zjoi2004]Swamp 沼泽鳄鱼 题解

[原题] 1898: [Zjoi2004]Swamp 沼泽鳄鱼 Time Limit: 5 Sec  Memory Limit: 64 MB Submit: 425  Solved: 256 [Submit][Status] Description 潘塔纳尔沼泽地号称世界上最大的一块湿地,它地位于巴西中部马托格罗索州的南部地区.每当雨季来临,这里碧波荡漾.生机盎然,引来不少游客.为了让游玩更有情趣,人们在池塘的中央建设了几座石墩和石桥,每座石桥连接着两座石墩,且每两座石墩之间至多只有一座石桥.这

[BZOJ 2326] [HNOI2011] 数学作业 【矩阵乘法】

题目链接:BZOJ - 2326 题目分析 数据范围达到了 10^18 ,显然需要矩阵乘法了! 可以发现,向数字尾部添加一个数字 x 的过程就是 Num = Num * 10^k + x .其中 k 是 x 的位数. 那么位数相同的数字用矩阵乘法处理就可以了. [Num, x, 1] * [10^k, 0, 0] = [Num*10^k+x, x+1, 1] [      1, 0, 0] [      0, 1, 1] 枚举位数,做多次矩阵乘法. 其中两个整数相乘可能会爆 LL ,那么就用类似

BZOJ 2326 HNOI2011 数学作业 矩阵乘法

题目大意:求1234567891011121314...n mod m 的值 设F(n)=1234567891011121314...n 那么显然有F(n)=F(n-1)*(floor(lgn)+1)+n 于是我们可以矩乘 将数字按照floor(lgn)+1分类 构造状态矩阵F(n) n+1 1 初值为0 1 1 1~9的转移矩阵为 10 0 0 1 1 0 0 1 1 10~99的转移矩阵为 100 0 0 1 1 0 0 1 1 以此类推 注意构造矩阵的时候要取模不然会挂 #include

bzoj 2326: [HNOI2011]数学作业

solution 矩阵: f:                         a:                                    10^k    0       0 ans    i    1    *                1       1       0                                       1       1       1 分段乘,给a赋值10^k时记得给10^k%上mod,不然炸long long了 1 #inc

矩阵乘法专题1——bzoj 1297 [SCOI2009] 迷路题解

题目链接 题意:给两个长度分别为n和m的序列,现在有两种操作:1.分别选择两个序列的一个非空前缀,切两个前缀的最后一位相同,删除之,得到1分(只累计),消耗e:2.直接删除两个序列,消耗值定于两个序列之前删除的元素个数之和,并且使得得到的分有效(之前没有有效分) 分析: 首先,问题其实就是转化成,进行若干次操作1,然后进行操作2 还要找到一个判别标准,来评判较优的状态(贪心) 每次的消耗值比较大,其实可以计算出最大的删除次数,这个值不是很大 状态表示: 简单的,一个状态可以表示为串A的位置.串B

矩阵乘法专题2——bzoj 1706 [usaco2007 Nov] relays 奶牛接力跑 题解

转载请注明:http://blog.csdn.net/jiangshibiao/article/details/24960651 [原题] 1706: [usaco2007 Nov]relays 奶牛接力跑 Time Limit: 5 Sec  Memory Limit: 64 MB Submit: 340  Solved: 162 [Submit][Status] Description FJ的N(2 <= N <= 1,000,000)头奶牛选择了接力跑作为她们的日常锻炼项目.至于进行接力

2326: [HNOI2011]数学作业

2326: [HNOI2011]数学作业 Description 不说什么ACTY了.. 题解: 线性的递推很容易写出来,f[i]=f[i-1]*10+i  (mod) 但是n很大,就需要用到矩阵乘法了.. 我们够造矩阵 10^i   0       0       f[i-1]        f[i] 1        1       0   *   i-1     =    i 1        1       1        1             1 #include<stdio.

【BZOJ 2326】 [HNOI2011]数学作业

2326: [HNOI2011]数学作业 Time Limit: 10 Sec  Memory Limit: 128 MB Submit: 1100  Solved: 625 [Submit][Status] Description 矩阵乘法. 可以用类似于秦九韶算法,把被取模的数拆开. 如123%m=(((1%m)*10+2)%m*10+3)%m 我们发现对于位数相同的数的计算方法是一样的,想到矩阵乘法. 对于1位的数: matrix x=10^1  0  0 1       1  0 0  

【BZOJ2326】[HNOI2011]数学作业 矩阵乘法

[BZOJ2326][HNOI2011]数学作业 题解:对于位数相同的数字,这显然是满足矩乘性质的. 那么我们枚举每一位,如果当前i=10^k,那么维护行向量(sum,now,1),now代表当前的数,每次将sum*=i再加上now,now+=1即可. #include <cstdio> #include <cstring> #include <iostream> using namespace std; typedef long long ll; ll n,P; st