bnu 34985 Elegant String(矩阵快速幂+dp推导公式)

Elegant String

Time Limit: 1000ms

Memory Limit: 65536KB

64-bit integer IO format: %lld     
Java class name: Main

Prev

Submit Status Statistics Discuss

Next

Type:

None

None Graph Theory 
    2-SAT     Articulation/Bridge/Biconnected Component
     Cycles/Topological Sorting/Strongly Connected Component
     Shortest Path 
        Bellman Ford         Dijkstra/Floyd Warshall
     Euler Trail/Circuit 
    Heavy-Light Decomposition     Minimum Spanning Tree
     Stable Marriage Problem 
    Trees     Directed Minimum Spanning Tree
     Flow/Matching 
        Graph Matching             Bipartite Matching
             Hopcroft–Karp Bipartite Matching
             Weighted Bipartite Matching/Hungarian Algorithm
         Flow 
            Max Flow/Min Cut             Min Cost Max Flow
 DFS-like 
    Backtracking with Pruning/Branch and Bound 
    Basic Recursion     IDA* Search 
    Parsing/Grammar     Breadth First Search/Depth First Search
     Advanced Search Techniques 
        Binary Search/Bisection         Ternary Search
 Geometry 
    Basic Geometry     Computational Geometry
     Convex Hull 
    Pick‘s Theorem Game Theory 
    Green Hackenbush/Colon Principle/Fusion Principle 
    Nim     Sprague-Grundy Number 
Matrix     Gaussian Elimination 
    Matrix Exponentiation Data Structures 
    Basic Data Structures     Binary Indexed Tree
     Binary Search Tree 
    Hashing     Orthogonal Range Search 
    Range Minimum Query/Lowest Common Ancestor 
    Segment Tree/Interval Tree     Trie Tree
     Sorting 
    Disjoint Set String 
    Aho Corasick     Knuth-Morris-Pratt 
    Suffix Array/Suffix Tree Math 
    Basic Math     Big Integer Arithmetic 
    Number Theory         Chinese Remainder Theorem
         Extended Euclid 
        Inclusion/Exclusion         Modular Arithmetic
     Combinatorics 
        Group Theory/Burnside‘s lemma         Counting
     Probability/Expected Value 
Others     Tricky 
    Hardest     Unusual 
    Brute Force     Implementation 
    Constructive Algorithms     Two Pointer 
    Bitmask     Beginner 
    Discrete Logarithm/Shank‘s Baby-step Giant-step Algorithm 
    Greedy     Divide and Conquer 
Dynamic Programming                  
Tag it!

We define a kind of strings as elegant string: among all the substrings of an elegant string, none of them is a permutation of "0, 1,…, k".

Let function(n, k) be the number of elegant strings of length n which only contains digits from 0 to k (inclusive). Please calculate function(n, k).

Input

Input starts with an integer T (T ≤ 400), denoting the number of test cases.

Each case contains two integers, n and k. n (1 ≤ n ≤ 1018) represents the length of the strings, and k (1 ≤ k ≤ 9) represents the biggest
digit in the string.

Output

For each case, first output the case number as "Case #x: ", and x is the case number. Then output function(n, k) mod 20140518 in this case.

Sample Input

2
1 1
7 6

Sample Output

Case #1: 2
Case #2: 818503

Source

2014 ACM-ICPC Beijing Invitational
Programming Contest

题解及代码:

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
typedef long long ll;
const long long mod=20140518;

struct mat
{
    ll t[10][10];
    void set()
    {
        memset(t,0,sizeof(t));
    }
} a,b;

mat multiple(mat a,mat b,ll n,ll p)
{
    ll i,j,k;
    mat temp;
    temp.set();
    for(i=0; i<n; i++)
        for(j=0; j<n; j++)
        {
            if(a.t[i][j]!=0)
                for(k=0; k<n; k++)
                    temp.t[i][k]=(temp.t[i][k]+a.t[i][j]*b.t[j][k])%p;
        }
    return temp;
}

mat quick_mod(mat b,ll n,ll m,ll p)
{
    mat t;
    t.set();
    for(ll i=0; i<n; i++) t.t[i][i]=1;
    while(m)
    {
        if(m&1)
        {
            t=multiple(t,b,n,p);
        }
        m>>=1;
        b=multiple(b,b,n,p);
    }
    return t;
}

void init(ll k)
{
    b.set();
    for(ll i=0; i<k; i++)
        b.t[i][0]=1;
    for(ll i=1; i<k; i++)
    {
        for(ll j=i-1; j<k; j++)
            if(j==i-1)
                b.t[j][i]=k-i+1;
            else b.t[j][i]=1;
    }
    /*
      for(int i=0;i<k;i++)
      {
          for(int j=0;j<k;j++)
            printf("%lld ",b.t[i][j]);
          puts("");
      }
     */
}

int main()
{
    int cas;
    ll n;
    ll k;
    scanf("%d",&cas);
    for(int ca=1; ca<=cas; ca++)
    {
        scanf("%lld%lld",&n,&k);
        init(k);
        a=quick_mod(b,k,n-1,mod);
        ll ans=0;
        for(ll i=0; i<k; i++)
        {
            ans=(ans+(k+1)*a.t[0][i])%mod;
        }
        printf("Case #%d: %lld\n",ca,ans);
    }
    return 0;
}
/*
北京邀请赛的题目,当时是学长A的,也从那时候开始,我知道了还有矩阵快速幂这个东西。
然后回到学校,就学习了一下,感觉主要就是dp公式的求解最重要了,其他的套模版就ok。

首先来说一下这道题目的题意:定义一个字符串,它的任意字串都不能存在0-k的任意全排列,
那么我们称这样的字符串为elegant string。
接下里我们定义一个函数F(n,k)为字符长度为n,使用0-k的字母来构成elegant string的数目。

因为n很大,所以很容易想到要使用矩阵快速幂来加速。
那么接下来就是推导公式了。
我们定义dp[i][j]为长度为i,尾部j个字母均不相同的字符串的数目。
那么我们很容易推出dp[i][j]的递推公式了:
dp[i][j]=dp[i-1][j-1]*(k-j+2)+dp[i-1][j]+……+dp[i-1][k];
这是什么意思呢?
首先我们知道,dp[i]和dp[i-1]只差一个字母,假设我们在dp[i-1]后面加上一个字母,这个
字母可以是和dp[i-1]尾部几个不同的字母中的一个相同,也可以不同(例:假如dp[i-1]=……0123,
k=7,这是我们为了构成dp[i],我们可以在尾部加上4、5、6、7,或者0、1、2、3)
大家会发现如果是4、5、6、7,那么dp[i-1][j-1]就变成了dp[i][j](看定义),
如果是0、1、2、3,那么dp[i-1][j-1]就会相应变成dp[i][j],dp[i][j-1],dp[i][j-2],dp[i][j-3],
综上我们为了构成dp[i][j],就可以使用dp[i-1][j-1]---dp[i-1][k]来构造。
然后剩下的事就是构造矩阵了,很简单,不赘述。

转载请注明出处,谢谢。
*/

bnu 34985 Elegant String(矩阵快速幂+dp推导公式),布布扣,bubuko.com

时间: 2024-07-30 10:11:20

bnu 34985 Elegant String(矩阵快速幂+dp推导公式)的相关文章

bnu 34895 Elegant String(矩阵快速幂)

题目链接:bnu 34895 Elegant String 题目大意:给定n和k,表示有一个长度为n的序列,序列中的元素由0~k组成,问说有多少个串满足不包含0~k的全排列. 解题思路:矩阵快速幂,根据dp[i][j]表示说第i为有j个相同,写出递推式,根据递推式求出矩阵. #include <cstdio> #include <cstring> typedef long long ll; const ll MOD = 20140518; const int N = 20; str

VOJ 1067 Warcraft III 守望者的烦恼 (矩阵快速幂+dp)

题目链接 显然可知 dp[n] = dp[n-k] + dp[n-k+1] + ... +dp[n-1]; 然后要用矩阵来优化后面的状态转移. 也就是矩阵 0 1 0 0    a     b 0 0 1 0 * b =  c 0 0 0 1    c     d 1 1 1 1    d    a+b+c+d 然后跑快速幂 #include <iostream> #include <cstdio> #include <algorithm> #include <c

P1357 花园 (矩阵快速幂+ DP)

题意:一个只含字母C和P的环形串 求长度为n且每m个连续字符不含有超过k个C的方案数 m <= 5  n <= 1e15 题解:用一个m位二进制表示状态 转移很好想 但是这个题是用矩阵快速幂加速dp的 因为每一位的转移都是一样的 用一个矩阵表示状态i能否转移到状态j 然后跑一遍 初试模板题 #include <bits/stdc++.h> using namespace std; typedef long long ll; const ll mod = 1e9 + 7; ll n,

COJ 1208 矩阵快速幂DP

题目大意: f(i) 是一个斐波那契数列 , 求sum(f(i)^k)的总和 由于n极大,所以考虑矩阵快速幂加速 我们要求解最后的sum[n] 首先我们需要思考 sum[n] = sum[n-1] + f(i+1)^k 那么很显然sum[n-1]是矩阵中的一个元素块 那么f(i+1)^k怎么利用f(i) , f(i-1)来求 f(i+1)^k = (f(i) + f(i-1)) ^ k 假如k = 1 , 可以看出f(i+1) = f(i-1) + f(i) (1,1) k = 2 , 可以看出

Codeforces 576D Flights for Regular Customers 矩阵快速幂+DP

题意: 给一个\(n\)点\(m\)边的连通图 每个边有一个权值\(d\) 当且仅当当前走过的步数\(\ge d\)时 才可以走这条边 问从节点\(1\)到节点\(n\)的最短路 好神的一道题 直接写做法喽 首先我们对边按\(d_i\)由小到大排序 设\(f_i\)表示加上\(1\sim i-1\)的所有边走\(d_i\)次后各点间的联通情况 \(G\)表示只连\(1\sim i-1\)的边的邻接矩阵 这些我们可以用一个\(01\)邻接矩阵来存储 则有 \(f_i=f_{i-1}*G^{d_i-

poj3744之矩阵快速幂+概率DP

Scout YYF I Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 4410   Accepted: 1151 Description YYF is a couragous scout. Now he is on a dangerous mission which is to penetrate into the enemy's base. After overcoming a series difficulties,

bnuoj 34985 Elegant String

题目链接:http://acm.bnu.edu.cn/bnuoj/problem_show.php?pid=34985 We define a kind of strings as elegant string: among all the substrings of an elegant string, none of them is a permutation of "0, 1,…, k". Let function(n, k) be the number of elegant s

【矩阵快速幂 】Codeforces 450B - Jzzhu and Sequences (公式转化)

[题目链接]click here~~ [题目大意] Jzzhu has invented a kind of sequences, they meet the following property: You are given x and y, please calculate fn modulo1000000007(109?+?7). [解题思路] /*A - Jzzhu and Sequences Codeforces 450B - Jzzhu and Sequences ( 矩阵快速幂 )

【HDOJ 4686】 Arc of Dream (矩阵快速幂)

[HDOJ 4686] Arc of Dream (矩阵快速幂) 两个公式 a(i) = a(i-1)*Ax+Ay b(i) = b(i-1)*Bx+By 求 0~(n-1) 的a(i)*b(i) 初始矩阵为                                       求幂矩阵为 a0                                                      Ax          0           0          0