出题人题解。
思路:
动态规划做法(60pts):
定义:
dp[i][1]→2
dp[i][2]→3
dp[i][3]→0,2
dp[i][4]→0,3
dp[i][5]→2,3
dp[i][6]→3,4
dp[i][7]→0,1,2
dp[i][8]→0,1,3
dp[i][9]→0,2,3
dp[i][10]→0,3,4
dp[i][11]→2,3,4
dp[i][12]→0,1,2,3
dp[i][13]→0,1,3,4
dp[i][14]→0,2,3,4
dp[i][15]→0,1,2,3,4
以上表示
i 位数中仅用了后面的数且满足题目要求的数的个数。
则状态转移方程为:
dp[i][1]=dp[i][2]=1
dp[i][3]=dp[i−1][1]+dp[i−1][3]×2
dp[i][4]=dp[i−1][2]+dp[i−1][4]×2
dp[i][5]=dp[i−1][1]+dp[i−1][2]+dp[i−1][5]×2
dp[i][6]=dp[i−1][2]+dp[i−1][6]
dp[i][7]=dp[i−1][3]+dp[i−1][7]×2
dp[i][8]=dp[i−1][4]+dp[i−1][8]×2
dp[i][9]=dp[i−1][3]+dp[i−1][4]+dp[i−1][5]+dp[i−1][9]×3
dp[i][10]=dp[i−1][4]+dp[i−1][6]+dp[i−1][10]×2
dp[i][11]=dp[i−1][5]+dp[i−1][6]+dp[i−1][11]×2
dp[i][12]=dp[i−1][7]+dp[i−1][8]+dp[i−1][9]+dp[i−1][12]×3
dp[i][13]=dp[i−1][8]+dp[i−1][10]+dp[i−1][13]×2
dp[i][14]=dp[i−1][9]+dp[i−1][10]+dp[i−1][11]+dp[i−1][14]×3
dp[i][15]=dp[i−1][12]+dp[i−1][13]+dp[i−1][14]+dp[i−1][15]×3
答案为:
dp[n][15]。
时间复杂度为
O(N),可以得到
30 分。
之后考虑矩阵快速幂:
100000000000000100000000000000102000000000000010200000000000110020000000000010001000000000001000200000000000100020000000001110003000000000101000200000000011000020000000000111003000000000010100200000000001110030000000000001113
之后按照初始矩阵
A(除了
(1,1) 和
(1,2) 处为
1,其他都为
0),进行快速幂即可。
时间复杂度为
O(logN×W3),W=15,可以获得 60pts。
组合数学做法(100pts)
考虑设序列
A={00⋯0011⋯11} 的长度为
x,序列
B={33⋯3344⋯44} 的长度为
y,则相当于将这两个序列插入到这
n 个位置中。
容易知道,若
A 的长度为
x,则可能的
A 有
(x−1) 个,
B 同理。
且由于首位不能为
0,则相当于在后面的
n−1 选
x 个放
A,然后在剩下的
n−x 个位置放
B,没放的显然是填
2,那么答案为:
Ans=x=2∑n−1y=2∑n−x−1(xn−1)(x−1)(yn−x)(y−1)=x=2∑n−2(xn−1)(x−1)(y=0∑n−x(yn−x)(y−1)−n+x+2)=x=2∑n−2(xn−1)(x−1)(y=0∑n−x(yn−x)y−2n−x−n+x+2)=x=2∑n−1(xn−1)(x−1)((n−x)y=0∑n−x(y−1n−x−1)−2n−x−n+x+2)=x=2∑n−1(xn−1)(x−1)((n−x)2n−x−1−2n−x−n+x+2)=x=0∑n−1(xn−1)(x−1)((n−x)2n−x−1−2n−x−n+x+2)+(n2n−1−2n−n+2)=x=0∑n−1(xn−1)x((n−x)2n−x−1−2n−x−n+x+2)−x=0∑n−1(xn−1)((n−x)2n−x−1−2n−x−n+x+2)+(n2n−1−2n−n+2)=(n−1)x=0∑n−2(xn−2)((n−x−1)2n−x−2−2n−x−1−n+x+3)−x=0∑n−1(xn−1)(n−x)2n−x−1+x=0∑n−1(xn−1)2n−x+n2n−1−(n−1)2n−2−2n+n2n−1−2n−n+2=(n−1)x=0∑n−2(xn−2)((n−x−1)2n−x−2−2n−x−1−n+x+3)−x=0∑n−1(xn−1)(n−x)2n−x−1+x=0∑n−1(xn−1)2n−x+(3n−7)2n−2−n+2=(n−1)x=0∑n−2(xn−2)((n−x−1)2n−x−2−2n−x−1−n+x+3)−nx=0∑n−1(xn−1)2n−x−1+x=0∑n−1(xn−1)x2n−x−1+2×3n−1+(3n−7)2n−2−n+2=(n−1)x=0∑n−2(xn−2)((n−x−1)2n−x−2−2n−x−1−n+x+3)+(n−1)x=0∑n−2(xn−2)2n−x−2−n3n−1+2×3n−1+(3n−7)2n−2−n+2=(n−1)x=0∑n−2(xn−2)((n−x−1)2n−x−2−2n−x−1−n+x+3)−(2n−5)3n−2+(3n−7)2n−2−n+2=(n−1)(x=0∑n−2(xn−2)(n−x−1)2n−x−2−x=0∑n−2(xn−2)2n−x−1−nx=0∑n−2(xn−2)+x=0∑n−2(xn−2)x+3x=0∑n−2(xn−2))−(2n−5)3n−2+(3n−7)2n−2−n+2=(n−1)((n−1)x=0∑n−2(xn−2)2n−x−2−x=0∑n−2(xn−2)x2n−x−2−2×3n−2−n2n−2+(n−2)2n−3+3×2n−2)−(2n−5)3n−2+(3n−7)2n−2−n+2=(n−1)((n−1)3n−2−(n−2)3n−3−2×3n−2−n2n−2+(n−2)2n−3+3×2n−2)−(2n−5)3n−2+(3n−7)2n−2−n+2=−5n3n−2−92n−2+2n23n−3+223n−3−n22n−3+11n2n−3−n+2
上面的推理运用了以下恒等式:
- ∑i=0n(in)=2n
证明:
考虑组合意义,在
n 个物品中选任意个,每个物品选或不选,方案数是
2n。
- (mn)m=n(m−1n−1)
证明:
(mn)m=m!(n−m)!n!m=(m−1)(n−m)!n!=n(m−1)!(n−m)!(n−1)!=n(m−1n−1)
- ∑i=0n(in)2n−i=3n
证明:
考虑组合意义,每个物品有三种形态,枚举仅有
i 个物品是第一种形态,则剩下的
n−i 个物品在剩下两种形态任选;等价于所有形态的方案数
3n。
时间复杂度为
O(len+logmod)。
主要考察选手组合数学基本功。
CPP#include<bits/stdc++.h>
#define lowbit(x) x & (-x)
#define ls(k) k << 1
#define rs(k) k << 1 | 1
#define fi first
#define se second
#define open(s1, s2) freopen(s1, "r", stdin), freopen(s2, "w", stdout);
#define int long long
using namespace std;
typedef __int128 __;
typedef long double lb;
typedef double db;
typedef unsigned long long ull;
typedef long long ll;
bool Begin;
const int N = 1e7 + 10, mod = 1e9 + 7;
inline ll read(){
ll x = 0, f = 1;
char c = getchar();
while(c < '0' || c > '9'){
if(c == '-')
f = -1;
c = getchar();
}
while(c >= '0' && c <= '9'){
x = (x << 1) + (x << 3) + (c ^ 48);
c = getchar();
}
return x * f;
}
inline void write(ll x){
if(x < 0){
putchar('-');
x = -x;
}
if(x > 9)
write(x / 10);
putchar(x % 10 + '0');
}
int n, mn, mbase = 1, len, sum, base = 1;
char s[N];
inline int qpow(int a, int b){
if(b < 0)
b += mod - 1;
int ans = 1;
while(b){
if(b & 1)
ans = 1ll * ans * a % mod;
a = 1ll * a * a % mod;
b >>= 1;
}
return ans;
}
bool End;
signed main(){
len = read();
scanf("%s", s + 1);
for(int i = len; i >= 1; --i){
n += (s[i] - '0') * base;
mn += (s[i] - '0') * mbase;
n %= mod;
mn %= (mod - 1);
base = base * 10ll % mod;
mbase = mbase * 10ll % (mod - 1);
}
sum = (mod - 5ll * n % mod * qpow(3, mn - 2) % mod) + (mod - 9ll * qpow(2, mn - 2) % mod) + 2ll * n % mod * n % mod * qpow(3, mn - 3) % mod + 22ll * qpow(3, mn - 3) % mod + (mod - n * n % mod * qpow(2, mn - 3) % mod) + 11ll * n % mod * qpow(2, mn - 3) % mod + (mod - n) + 2;
write(sum % mod);
cerr << '\n' << abs(&Begin - &End) / 1048576 << "MB";
return 0;
}