• hiho1560


    题目链接

    坑死了,以为是K进制数,每一位可以是0-K之间的,其实是十进制,每一位最高为9,一直wa在这。。。。。。。

    ----------------------------------------------------------------------------------------------------------------------------------------------------

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

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

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

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

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

    -----------------------------------------------------------------------------------------------------------------------------------------------------

    找完规律后,典型的矩阵快速幂

    #include <set>
    #include <map>
    #include <stack>
    #include <queue>
    #include <cmath>
    #include <vector>
    #include <string>
    #include <cstdio>
    #include <cstring>
    #include <cstdlib>
    #include <iostream>
    #include <algorithm>
    
    #define MAX(a,b) ((a)>=(b)?(a):(b))
    #define MIN(a,b) ((a)<=(b)?(a):(b))
    #define OO 0x0fffffff
    using namespace std;
    typedef long long LL;
    const int N = 16;
    const LL MOD = 1E9+7;
    int k;
    struct Mat{
        int dim;
        LL data[N][N];
        Mat(int n){
            memset(data,0,sizeof(data));
            for(int i=0; i<=n; i++) for(int j=0; j<=n; j++){
                if(i*j<=k) data[i][j]=1;
            }
            dim = n+1;
        }
        Mat(){ memset(data,0,sizeof(data)); }
        LL* operator[] (size_t idx){ return data[idx];}
        friend Mat operator*(Mat& a,Mat& b){
            Mat ret;
            ret.dim = a.dim;
            for(int i=0; i<ret.dim; i++) for(int j=0; j<ret.dim; j++) for(int k=0; k<ret.dim; k++){
                  ret[i][j]+=a[i][k]*b[k][j];
                  if(ret[i][j]>=MOD) ret[i][j]%=MOD;
            }
            return ret;
        }
    };
    int main(){
        LL n;
        while(scanf("%lld%d",&n,&k)!=EOF){
            if(n==1) printf("%d
    ",k);
            else{
                vector<int> dits;
                n--;
                while(n){
                    if(n&1) dits.push_back(1);
                    else dits.push_back(0);
                    n>>=1;
                }
                Mat base(MIN(k,9));
                Mat ans = base;
                for(int i=dits.size()-2; i>=0; i--){
                    ans=ans*ans;
                    if(dits[i]==1) ans=ans*base;
                }
                LL result = 0;
                for(int i=0; i<ans.dim; i++) for(int j=1; j<ans.dim; j++){
                    result = (result + ans[i][j])%MOD;
                }
                printf("%lld
    ",result);
            }
        }
        return 0;
    }
  • 相关阅读:
    CopyOnWriteArrayList设计思路与源码分析
    点击页面按钮以excel保存到本地
    上传图片
    关于重复点击的
    去首尾空格还有换行问题//把数字换位大写字母//向后台传输数据
    判断输入的时间与当前的时间(判断时间是今天还是以前的)
    前端的一些小技巧
    git 操作大全
    移动web开发常见问题解决方案
    响应式布局
  • 原文地址:https://www.cnblogs.com/redips-l/p/7424188.html
Copyright © 2020-2023  润新知