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


    数学作业

    Time Limit: 10 Sec  Memory Limit: 128 MB
    [Submit][Status][Discuss]

    Description

      

    Input

      输入文件只有一行为用空格隔开的两个正整数N和M。

    Output

      输出仅包含一个非负整数,表示Concatenate(1~N) MOD M的值。

    Sample Input

      12345678910 1000000000

    Sample Output

      345678910

    HINT

      1<=N<=10^8 , 1<=M<=10^9

    Main idea

      给定一个n,m,创造一个数字顺序连接1~n,输出这个数对m取模的值。

    Solution

      n<=10^18,排除找规律的可能性,立马想到了用矩阵乘法优化DP,令f[i]表示1~i的值,那么:

      然后我们只要推出矩阵即可,轻松想到了:

      然后分段矩乘得到答案。

    Code

     1 #include<iostream>  
     2 #include<string>  
     3 #include<algorithm>  
     4 #include<cstdio>  
     5 #include<cstring>  
     6 #include<cstdlib>  
     7 #include<cmath>  
     8 using namespace std;  
     9  
    10 const int ONE=5;
    11  
    12 long long n,MOD;
    13 long long a[ONE][ONE],b[ONE][ONE];
    14 long long Index;
    15  
    16  
    17 void Mul(long long a[ONE][ONE],long long b[ONE][ONE],long long ans[ONE][ONE])
    18 {
    19         long long jilu[ONE][ONE];
    20         for(int i=1;i<=3;i++)
    21         for(int j=1;j<=3;j++)
    22         {
    23             jilu[i][j]=0;
    24             for(int k=1;k<=3;k++)
    25             jilu[i][j]=(jilu[i][j] + a[i][k]*b[k][j]%MOD) % MOD;
    26         }
    27          
    28         for(int i=1;i<=3;i++)
    29         for(int j=1;j<=3;j++)
    30         ans[i][j]=jilu[i][j];
    31 }
    32  
    33 void Matrix(long long a[ONE][ONE],long long b[ONE][ONE],long long t)
    34 {
    35         while(t)
    36         {
    37             if(t&1) Mul(a,b,a);
    38             Mul(b,b,b);
    39             t>>=1;
    40         }
    41 }
    42  
    43 int main()
    44 {
    45         cin>>n>>MOD;
    46         a[1][3]=1;
    47          
    48         long long len=1;
    49         for(;;)
    50         {
    51             len*=10;
    52             memset(b,0,sizeof(b));
    53             for(int i=1;i<=3;i++)
    54             {
    55                 for(int j=1;j<=i;j++)
    56                 b[i][j]=1;  
    57             }
    58             b[1][1]=len % MOD;
    59              
    60             if(len<=n) Index=len-len/10;
    61             else Index=n-len/10+1;
    62             Matrix(a,b,Index);
    63             if(len>n) break;
    64         }
    65          
    66         printf("%lld",a[1][1]);
    67 }
    View Code
  • 相关阅读:
    路由懒加载
    Generator函数
    属性特性get/set
    审核功能
    纯js实现最简单的文件上传(后台使用MultipartFile)
    shiro+redis多次调用doReadSession方法的解决方案
    nginx-windows版
    Spring—Quartz定时调度CronTrigger时间配置格式说明与实例
    java中获取文件目录
    mysql 在update中实现子查询的方式
  • 原文地址:https://www.cnblogs.com/BearChild/p/6441341.html
Copyright © 2020-2023  润新知