zoukankan      html  css  js  c++  java
  • 【HDU1757】A Simple Math Problem

    题目链接

    A Simple Math Problem

    题目描述

    Lele now is thinking about a simple function f(x).

    • If x < 10 f(x) = x.
    • If x >= 10 f(x) = a0(*)f(x-1)+a1(*)f(x-2)+a2(*)f(x-3)+……+a9(*)f(x-10);
    • And ai(0<=i<=9) can only be 0 or 1 .

    Now, I will give a0 ~ a9 and two positive integers k and m ,and could you help Lele to caculate f(k)%m.

    输入格式

    The problem contains mutiple test cases.Please process to the end of file.
    In each case, there will be two lines.
    In the first line , there are two positive integers k and m. ( k<2*10^9 , m < 10^5 )
    In the second line , there are ten integers represent a0 ~ a9.

    输出格式

    For each case, output (f)((k))(\% m) in one line.

    样例输入

    10 9999
    1 1 1 1 1 1 1 1 1 1
    20 500
    1 0 1 0 1 0 1 0 1 0
    

    样例输出

    45
    104
    

    题解

    题意:一个函数(f)((x))满足:
    (x < 10)时,(f)((x))(=x)
    (x ge 10)时,(f)((x))(=sum_{i=1}^{10}a_{i-1}*f)((x-i))
    输入(x)满足(x<2*10^9)
    (f)((x))
    看到数据范围是(int)范围的,那么(O)((n))求解肯定是不行的。
    看到这个函数的转移方程,是不是很像斐波那契数列呢?
    众所周知,斐波那契数列有一个矩阵快速幂的加速方法,同理我们也可以用这个方法加速这个函数。
    这个函数中,(f)((n))只和他的前10项有关,那么我们构造的矩阵只需要包含(10)个元素就行了。
    矩阵的构造如下:

    那么接下来直接用矩阵快速幂加速就好了。
    (F)((k))(=A^{k-9}*B)
    上代码:

    #include<bits/stdc++.h>
    using namespace std;
    int k,m;
    int a[19];
    struct aa{
        long long a[19][19];
    };
    aa cc(aa x,aa y){
        aa ans;
        for(int j=1;j<=10;j++)
            for(int i=1;i<=10;i++){
                ans.a[j][i]=0;
                for(int o=1;o<=10;o++)
                    ans.a[j][i]=(ans.a[j][i]+x.a[j][o]*y.a[o][i])%m;
            }
        return ans;
    }
    aa ksm(aa x,int p){
        aa ans;
        for(int j=1;j<=10;j++)
            for(int i=1;i<=10;i++)
                ans.a[j][i]=(j==i);
        while(p){
            if(p&1) ans=cc(ans,x);
            x=cc(x,x);
            p>>=1;
        }
        return ans;
    }
    int main(){
        while(scanf("%d%d",&k,&m)!=EOF){
            for(int j=1;j<=10;j++)
                scanf("%d",&a[j]);
            aa x;
            for(int j=1;j<=10;j++)
                x.a[1][j]=a[j];
            for(int j=2;j<=10;j++)
                for(int i=1;i<=10;i++)
                    x.a[j][i]=(j==i+1);
            aa ans=ksm(x,k-9);
            int anss=0;
            for(int j=1;j<=10;j++)
                anss=(anss+ans.a[1][j]*(10-j))%m;
            printf("%d
    ",anss);
        }
        return 0;
    }
    
  • 相关阅读:
    linux设置系统变量
    linux通配符
    linux 别名
    echo 输出颜色
    Linux:echo命令详解
    poj 2456 Aggressive cows 二分 题解《挑战程序设计竞赛》
    poj 1064 Cable master 二分 题解《挑战程序设计竞赛》
    染色法判定二分图 模板 题解《挑战程序设计竞赛》
    poj 1182 食物链 并查集 题解《挑战程序设计竞赛》
    poj 2431 Expedition 贪心 优先队列 题解《挑战程序设计竞赛》
  • 原文地址:https://www.cnblogs.com/linjiale/p/13477454.html
Copyright © 2011-2022 走看看