题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=2326

题意:定义Concatenate(1,N)=1234567……n。比如Concatenate(1,10)=12345678910。给定n和m,求Concatenate(1,n)%m。

思路:令f[n]表示Concatenate(1,n)。那么有:

f[i]=f[i-1]*10+(i-1)+1   1<=i<=9

f[i]=f[i-1]*100+(i-1)+1  10<=i<=99

……

因此可用矩阵加速:

但是,这个矩阵是分段的。

#include <iostream>
#include <cstdio>
#include <string.h>
#include <algorithm>
#include <cmath>
#include <vector>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <map>

#define max(x,y) ((x)>(y)?(x):(y))
#define min(x,y) ((x)<(y)?(x):(y))
#define abs(x) ((x)>=0?(x):-(x))
#define i64 long long
#define u32 unsigned int
#define u64 unsigned long long
#define clr(x,y) memset(x,y,sizeof(x))
#define CLR(x) x.clear()
#define ph(x) push(x)
#define pb(x) push_back(x)
#define Len(x) x.length()
#define SZ(x) x.size()
#define PI acos(-1.0)
#define sqr(x) ((x)*(x))
#define MP(x,y) make_pair(x,y)
#define EPS 1e-10

#define FOR0(i,x) for(i=0;i<x;i++)
#define FOR1(i,x) for(i=1;i<=x;i++)
#define FOR(i,a,b) for(i=a;i<=b;i++)
#define FORL0(i,a) for(i=a;i>=0;i--)
#define FORL1(i,a) for(i=a;i>=1;i--)
#define FORL(i,a,b)for(i=a;i>=b;i--)

#define rush() int CC;for(scanf("%d",&CC);CC--;)
#define Rush(n)  while(scanf("%d",&n)!=-1)
using namespace std;

void RD(int &x){scanf("%d",&x);}
void RD(i64 &x){scanf("%lld",&x);}
void RD(u64 &x){scanf("%I64u",&x);}
void RD(u32 &x){scanf("%u",&x);}
void RD(double &x){scanf("%lf",&x);}
void RD(int &x,int &y){scanf("%d%d",&x,&y);}
void RD(i64 &x,i64 &y){scanf("%lld%lld",&x,&y);}
void RD(u32 &x,u32 &y){scanf("%u%u",&x,&y);}
void RD(double &x,double &y){scanf("%lf%lf",&x,&y);}
void RD(int &x,int &y,int &z){scanf("%d%d%d",&x,&y,&z);}
void RD(i64 &x,i64 &y,i64 &z){scanf("%lld%lld%lld",&x,&y,&z);}
void RD(u32 &x,u32 &y,u32 &z){scanf("%u%u%u",&x,&y,&z);}
void RD(double &x,double &y,double &z){scanf("%lf%lf%lf",&x,&y,&z);}
void RD(char &x){x=getchar();}
void RD(char *s){scanf("%s",s);}
void RD(string &s){cin>>s;}

void PR(int x) {printf("%d\n",x);}
void PR(int x,int y) {printf("%d %d\n",x,y);}
void PR(i64 x) {printf("%lld\n",x);}
void PR(u32 x) {printf("%u\n",x);}
void PR(u64 x) {printf("%llu\n",x);}
void PR(double x) {printf("%.2lf\n",x);}
void PR(char x) {printf("%c\n",x);}
void PR(char *x) {printf("%s\n",x);}
void PR(string x) {cout<<x<<endl;}

const int mod=10007;
const i64 inf=((i64)1)<<60;
const double dinf=1000000000000000000.0;
const int INF=1000000005;
const int N=405;

i64 n,m;

struct Matrix
{
    i64 a[3][3];

void init(int x)
    {
        clr(a,0);
        if(x==1) a[0][0]=a[1][1]=a[2][2]=1;
    }

Matrix operator*(Matrix p)
    {
        Matrix ans;
        ans.init(0);
        int i,j,k;
        FOR0(k,3) FOR0(i,3) FOR0(j,3)
        {
            ans.a[i][j]+=a[i][k]*p.a[k][j]%m;
            ans.a[i][j]%=m;
        }
        return ans;
    }

Matrix power(i64 n)
    {
        Matrix ans,p=*this;
        ans.init(1);
        while(n)
        {
            if(n&1) ans=ans*p;
            p=p*p;
            n>>=1;
        }
        return ans;
    }
};

i64 p[20];

void init()
{
    int i;
    p[0]=1;
    for(i=1;i<=18;i++) p[i]=p[i-1]*10;
}

Matrix cal(i64 n,i64 k)
{
    Matrix a;
    a.init(0);
    a.a[0][0]=k;
    a.a[1][0]=a.a[1][1]=a.a[2][0]=a.a[2][1]=a.a[2][2]=1;
    return a.power(n);
}

int main()
{
    RD(n,m); init(); Matrix b; b.init(1);
    i64 i,L,R;
    for(i=1;;i++)
    {
        L=p[i-1];
        R=min(p[i]-1,n);
        b=b*cal(R-L+1,p[i]%m);
        if(R==n) break;
    }
    PR(b.a[2][0]);
}

BZOJ 2326 数学作业(矩阵)的更多相关文章

  1. BZOJ 2326 数学作业(分段矩阵快速幂)

    实际上,对于位数相同的连续段,可以用矩阵快速幂求出最后的ans,那么题目中一共只有18个连续段. 分段矩阵快速幂即可. #include<cstdio> #include<iostr ...

  2. CJOJ 1331 【HNOI2011】数学作业 / Luogu 3216 【HNOI2011】数学作业 / HYSBZ 2326 数学作业(递推,矩阵)

    CJOJ 1331 [HNOI2011]数学作业 / Luogu 3216 [HNOI2011]数学作业 / HYSBZ 2326 数学作业(递推,矩阵) Description 小 C 数学成绩优异 ...

  3. BZOJ 2326: [HNOI2011]数学作业( 矩阵快速幂 )

    BZOJ先剧透了是矩阵乘法...这道题显然可以f(x) = f(x-1)*10t+x ,其中t表示x有多少位. 这个递推式可以变成这样的矩阵...(不会用公式编辑器...), 我们把位数相同的一起处理 ...

  4. BZOJ-2326 数学作业 矩阵乘法快速幂+快速乘

    2326: [HNOI2011]数学作业 Time Limit: 10 Sec Memory Limit: 128 MB Submit: 1564 Solved: 910 [Submit][Statu ...

  5. [HNOI2011]数学作业 --- 矩阵优化

    [HNOI2011]数学作业 题目描述: 小 C 数学成绩优异,于是老师给小 C 留了一道非常难的数学作业题: 给定正整数 N 和 M ,要求计算\(Concatenate(1..N)\; Mod\; ...

  6. 洛谷P3216 [HNOI2011] 数学作业 [矩阵加速,数论]

    题目传送门 数学作业 题目描述 小 C 数学成绩优异,于是老师给小 C 留了一道非常难的数学作业题: 给定正整数 N和 M,要求计算 Concatenate (1 .. N)Mod M 的值,其中 C ...

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

    数学作业 Time Limit: 10 Sec  Memory Limit: 128 MB[Submit][Status][Discuss] Description Input 输入文件只有一行为用空 ...

  8. [HNOI2011]数学作业 矩阵快速幂 BZOJ 2326

    题目描述 小 C 数学成绩优异,于是老师给小 C 留了一道非常难的数学作业题: 给定正整数 NNN 和 MMM ,要求计算Concatenate(1..N) Concatenate (1 .. N) ...

  9. BZOJ 2326: [HNOI2011]数学作业(矩阵乘法)

    传送门 解题思路 NOIp前看到的一道题,当时想了很久没想出来,NOIp后拿出来看竟然想出来了.注意到有递推\(f[i]=f[i-1]*poww[i]+i\),\(f[i]\)表示\(1-i\)连接起 ...

随机推荐

  1. 【学习总结】iOS 数据保存几种方式总结

    在iOS开发过程中,不管是做什么应用,都会碰到数据保存的问题.将数据保存到本地,能够让程序的运行更加流畅,不会出现让人厌恶的菊花形状,使得用户体验更好.下面介绍一下数据保存的方式: NSKeyedAr ...

  2. SOLID architecture principles using simple C# examples

    转:http://www.codeproject.com/Articles/703634/SOLID-architecture-principles-using-simple-Csharp?msg=4 ...

  3. Hibernate各种主键生成策略与配置详解【附1--<generator class="foreign">】

    1.assigned 主键由外部程序负责生成,在 save() 之前必须指定一个.Hibernate不负责维护主键生成.与Hibernate和底层数据库都无关,可以跨数据库.在存储对象前,必须要使用主 ...

  4. 用两个栈来实现一个队列,完成队列的Push和Pop操作。 队列中的元素为int类型。

    // test14.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #include<iostream> #include< ...

  5. 【BZOJ】【3669】【NOI2014】魔法森林

    LCT动态维护MST LCT动态维护MST 我们可以枚举a,然后找从1到n的一条路径使得:这条路径上的b的最大值最小.这个路径肯定在MST上……所以枚举一遍所有的边,动态维护一个关于b值的MST即可. ...

  6. C#中两个日期类型相减得到天数

    protected int GetDuration(DateTime start, DateTime finish) { return (finish - start).Days; } 直接相减得到的 ...

  7. STL中的stack(堆栈)

    转载:http://blog.csdn.net/morewindows/article/details/6950881 栈(statck)这种数据结构在计算机中是相当出名的.栈中的数据是先进后出的(F ...

  8. Chp18: Hard

    18.1 Write a function that adds two numbers. You should not use + or any arithmetic operators. Solut ...

  9. java基础知识回顾之java Thread类学习(六)--java多线程同步函数用的锁

    1.验证同步函数使用的锁----普通方法使用的锁 思路:创建两个线程,同时操作同一个资源,还是用卖票的例子来验证.创建好两个线程t1,t2,t1线程走同步代码块操作tickets,t2,线程走同步函数 ...

  10. hdu 4686 Arc of Dream

    思路:构造矩阵 a[i]*b[i]=ax*bx*a[i-1]*b[i-1]+ax*by*a[i-1]+ay*bx*b[i-1]+ay*by 代码如下: #include<iostream> ...