zoukankan      html  css  js  c++  java
  • [HNOI2011]数学作业 题解

      这道题看着挺难然而其实看破了也挺容易的。首先N极其的大,几乎要炸掉long long ,所以O(n)的算法一定是扑街了,身为一个脑残志坚的OIer,怎能不想到矩阵快速幂优化呢? 

      有趣的是这道题矩阵有很多种,Q某犇有另一种做法,大家也可以去他那看一看。

      答案矩阵是这样的:

        f[x]   x+1   1

      被我们用来求答案的矩阵长这样:

        10^t     0      0

        1         1      0

        0         1      1

       其中t随我们现在处理的数的位数而改变。

      然后这道题就硬生生的被我们搞成了一个矩阵快速幂的裸题。只要注意矩阵乘不满足交换律就是了。

      

     1 #include<iostream>
     2 #include<cstdlib>
     3 #include<cstdio>
     4 #include<cstring>
     5 #include<algorithm>
     6 #include<map>
     7 #include<queue>
     8 #include<string>
     9 #include<cmath>
    10 using namespace std;
    11 long long n,m;
    12 struct no{
    13     long long x,y;
    14     long long a[20][20];
    15     no operator *(const no &c){
    16         no b;
    17         memset(b.a,0,sizeof(b.a));
    18         b.x=x;
    19         b.y=y;
    20         for(int i=1;i<=x;i++)
    21         {
    22             for(int j=1;j<=y;j++)
    23             {
    24                 for(int k=1;k<=y;k++)
    25                 {
    26                     b.a[i][j]+=((a[i][k]%m)*(c.a[k][j]%m))%m;
    27                     b.a[i][j]%=m;
    28                 }
    29             }
    30         }
    31         return b;
    32     }
    33 };
    34 no ksm(long long x,no a,no b){
    35     no ans=a;
    36     while(x)
    37     {
    38         if((x&1)) ans=ans*b;
    39         b=b*b;
    40         x>>=1;
    41     }
    42     return ans;
    43 }
    44 long long get(long long x){
    45     long long now=1;
    46     no ans,a;
    47     memset(a.a,0,sizeof(a.a));
    48     a.x=a.y=3;
    49     a.a[2][1]=a.a[2][2]=a.a[3][2]=a.a[3][3]=1;
    50     memset(ans.a,0,sizeof(ans.a));
    51     ans.x=1,ans.y=3;
    52     ans.a[1][1]=0;
    53     ans.a[1][2]=ans.a[1][3]=1;
    54     for(int i=1;;i++)
    55     {
    56         now*=10;
    57         if(x>(now-1))
    58         {
    59             a.a[1][1]=now;
    60             ans=ksm(now-now/10,ans,a);
    61         }
    62         else
    63         {
    64             a.a[1][1]=now;
    65             ans=ksm(x-(now/10-1),ans,a);
    66             break;
    67         }
    68     }
    69     return ans.a[1][1];
    70 }
    71 int main(){
    72     scanf("%lld%lld",&n,&m);
    73     printf("%lld
    ",get(n));
    74     //while(1);
    75     return 0;
    76 }
    View Code
  • 相关阅读:
    02:找第一个只出现一次的字符
    11-Canvas
    07-jQuery
    06-JavaScript高级
    05-Web API
    03-京东项目
    剑与远征-兑换码
    04-JavaScript基础语法
    02-CSS
    01-HTML
  • 原文地址:https://www.cnblogs.com/liutianrui/p/7360281.html
Copyright © 2011-2022 走看看