4037: [haoi2015]數字串拆分
time limit: 10 sec memory limit: 256 mb
description
你有乙個長度為n的數字串。定義f(s)為將s拆分成若干個1~m的數的和的方案數,比如m=2時,f(4)=5,分別為4=1+1+1+1你可以將這個數字串分割成若干個數字(允許前導0),將他們加起來,求f,並求和。比如g(123)=f(1+2+3)
+f(1+23)+f(12+3)+f(123)。已知字串和m後求答案對998244353(7×17×223+1,乙個質數)取模後的值。
input
第一行輸入乙個字串,第二行輸入m
output
僅輸出乙個數表示答案
sample input
123
3 sample output
394608467
hint
對於100%的資料,字串長度不超過500,m<=5
失蹤人口回歸
這題的是一道真正的」矩陣上的dp」…
首先,我們可以得到f陣列的狀態轉移方程 f[
i]=∑
j=0m
f[i−
j]我們可以很容易遞推f陣列(矩陣優化)
構造的矩陣大概是這樣(以m=4為例)
1 1 0 0
1 0 1 0
1 0 0 1
1 0 0 0
然後將這個矩陣自乘n次,s[0][0]即是f
n; 接下來才是二逼的地方.
設f0為f函式前m項構成的向量,f[i][j]為數字i的10^j所對應的狀態矩陣,
即f[i][0]為能將f0轉移到fi的狀態矩陣,f[i][1]為能將f0轉移到fi*10的狀態矩陣,
f[i][2]為能將f0轉移到fi*100的狀態矩陣……
考慮在字串上的dp
因為f函式不直接滿足分配率,所以我們不能直接用如下方程 dp
[i]=
∑j=0
i−1d
p[j]
×f[j
+1...i]
然而f可以寫成矩陣的冪的形式,提取公因式後可以滿足分配律,
所以如下狀態轉移方程成立 dp
[i]=
∑j=0
i−1d
p[j]
×mm為[i+1,j]所對應的狀態矩陣.
所以我們可以愉快的進行矩陣快速冪了…(真正的」矩陣上的dp」)
這就是所謂的十進位制快速冪.
答案就是dp[n][0][0];
**
#include
#include
#define mem(a,b) memset(a,b,sizeof(a))
inline
void read(int& x)
while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
x*=y;
}typedef
unsigned
long
long ull;
const
int mod=998244353;
int m,n;
char t[505];
struct matrix
inline
int *operator (int x)
inline
void init()
inline
void pre()
inline
friend matrix operator *(matrix x,matrix y)
return z;
}inline
friend matrix operator +(matrix x,matrix y)
}f[10][505],dp[505];
inline matrix qp(matrix x,int y)
inline
void init()
}}int main()
HAOI2015 數字串拆分
你有乙個長度為n的數字串。定義f s 為將s拆分成若干個1 m的數的和的方案數,比如m 2時,f 4 5,分別為4 1 1 1 1你可以將這個數字串分割成若干個數字 允許前導0 將他們加起來,求f,並求和。比如g 123 f 1 2 3 f 1 23 f 12 3 f 123 已知字串和m後求答案對...
4037 HAOI2015 數字串拆分
time limit 10 sec memory limit 256 mb submit 255 solved 156 submit status discuss 你有乙個長度為n的數字串。定義f s 為將s拆分成若干個1 m的數的和的方案數,比如m 2時,f 4 5,分別為4 1 1 1 1你可以...
HAOI2015 bzoj4037 數字串拆分
description 你有乙個長度為n的數字串。定義f s 為將s拆分成若干個1 m的數的和的方案數,比如m 2時,f 4 5,分別為4 1 1 1 1你可以將這個數字串分割成若干個數字 允許前導0 將他們加起來,求f,並求和。比如g 123 f 1 2 3 f 1 23 f 12 3 f 123...