zoukankan      html  css  js  c++  java
  • #1560 : H国的身份证号码II(dp+矩阵快速幂)

    #1560 : H国的身份证号码II

     

    时间限制:10000ms
    单点时限:1000ms
    内存限制:256MB

    描述

    H国的身份证号码是一个N位的正整数(首位不能是0)。此外,由于防伪需要,一个N位正整数是合法的身份证号码当且仅当每位数字都小于等于K,并且任意相邻两位数字的乘积也小于等于K。

    例如对于K=5, 101、211、210等都是合法的号码,而106、123、421等都是非法的号码。

    给定一个正整数N以及K,H国总统想知道一共有多少个合法的号码可用。

    输入

    两个整数N和K。

    对于30%的数据,1 ≤ N ≤ 10  

    对于50%的数据,1 ≤ N ≤ 1000000

    对于100%的数据,1 ≤ N ≤ 1012,1 ≤ K ≤ 81。

    输出

    合法号码的总数。由于答案可能非常大,你只需要输出答案对109+7取模的结果。

    样例输入

    2 4

    样例输出

    12

    //dp[i][j] 代表 i 长度,结尾为 j 的合法方案数

    那么容易想到

    i = 1 : dp[1][j] = 1 (j<=k)

    i > 1 : dp[i][j] = ∑dp[i-1][x] (x<=k&&j<=k&&j*x<=k)
    可以发现,可以用矩阵快速幂优化,O(103*logn)
      1 # include <cstdio>
      2 # include <cstring>
      3 # include <cstdlib>
      4 # include <iostream>
      5 # include <vector>
      6 # include <queue>
      7 # include <stack>
      8 # include <map>
      9 # include <bitset>
     10 # include <sstream>
     11 # include <set>
     12 # include <cmath>
     13 # include <algorithm>
     14 # pragma  comment(linker,"/STACK:102400000,102400000")
     15 using namespace std;
     16 # define LL          long long
     17 # define pr          pair
     18 # define mkp         make_pair
     19 # define lowbit(x)   ((x)&(-x))
     20 # define PI          acos(-1.0)
     21 # define INF         0x3f3f3f3f3f3f3f3f
     22 # define eps         1e-8
     23 # define MOD         1000000007
     24 
     25 inline int scan() {
     26     int x=0,f=1; char ch=getchar();
     27     while(ch<'0'||ch>'9'){if(ch=='-') f=-1; ch=getchar();}
     28     while(ch>='0'&&ch<='9'){x=x*10+ch-'0'; ch=getchar();}
     29     return x*f;
     30 }
     31 inline void Out(int a) {
     32     if(a<0) {putchar('-'); a=-a;}
     33     if(a>=10) Out(a/10);
     34     putchar(a%10+'0');
     35 }
     36 #define MX 10
     37 /**************************/
     38 struct Mat
     39 {
     40     LL m[MX][MX];
     41 }unit,di,fir;
     42 
     43 LL n,k;
     44 
     45 Mat mult(Mat a,Mat b)
     46 {
     47     Mat c;
     48     for (int i=0;i<MX;i++)
     49         for (int j=0;j<MX;j++)
     50         {
     51             c.m[i][j]=0;
     52             for (int k=0;k<MX;k++)
     53                 c.m[i][j]=(c.m[i][j]+a.m[i][k]*b.m[k][j])%MOD;
     54         }
     55     return c;
     56 }
     57 
     58 Mat cal(LL p)
     59 {
     60     Mat ret = unit, b = di;
     61     while (p)
     62     {
     63         if (p&1) ret = mult(ret,b);
     64         b = mult(b,b);
     65         p/=2;
     66     }
     67     return ret;
     68 }
     69 
     70 void Init()
     71 {
     72     for (int i=0;i<MX;i++)
     73         unit.m[i][i]=1;
     74     for (int i=1;i<MX;i++)
     75     {
     76         if (i<=k)
     77             fir.m[i][0]=1;
     78     }
     79     for (int i=0;i<MX;i++)
     80     {
     81         for (int j=0;j<MX;j++)
     82         {
     83             if (i<=k&&j<=k&&i*j<=k)
     84                 di.m[i][j]=di.m[j][i]=1;
     85         }
     86     }
     87 }
     88 
     89 int main()
     90 {
     91     scanf("%lld%lld",&n,&k);
     92     Init();
     93     Mat sa = fir;
     94     Mat sb = cal(n-1);
     95     sb = mult(sb,sa);
     96 
     97     LL ans = 0;
     98     for (int i=0;i<MX;i++)
     99     {
    100         ans = (ans + sb.m[i][0])%MOD;
    101     }
    102     printf("%lld
    ",ans);
    103     return 0;
    104 }
    View Code
  • 相关阅读:
    python 递归计算阶乘
    python引用
    python3 函数参数
    名片管理系统V0.0.2(函数实现)
    python 之socket语法及相关
    常见模块(一)
    常见模块(二)
    Python之迭代器、生成器、装饰器和递归
    python 之自定义函数
    python 之SET和collections
  • 原文地址:https://www.cnblogs.com/haoabcd2010/p/7403240.html
Copyright © 2011-2022 走看看