QOJ7018 Insertion Sort
原题链接:Insertion Sort
分析
分讨的本质就是有问题的。如果继续容斥的话,那就完蛋了。
正确的式子就是:
a n s = k ! × ( 1 + C n − k 1 × C n − 1 1 ) ans=k!\times(1+C_{n-k}^{1}\times C_{n-1}^{1}) ans=k!×(1+Cn−k1×Cn−11)
就是相当于前 k k k 的全排,后面的 1 1 1 是序列完全有序,后面的相当于在剩下的 n − k n-k n−k 里挑一个,然后插到剩下里面去,做完了。
所以,我真的想到了吗?可能吧,不过,确实少了一些东西吧......
下次最好先打一个表!!!
哦,我推出来......但是,我插板的时候按照 n n n 来算了😭
正解
cpp
#include <bits/stdc++.h>
#define int long long
using namespace std;
int T;
int n, k, p;
signed main(){
// freopen("prefixsort.in", "r", stdin);
// freopen("prefixsort.out", "w", stdout);
cin >> T;
for (int cs = 1; cs <= T; cs++){
cin >> n >> k >> p;
k = min(n, k);
int ans = (1 + (n - k) * (n - 1) % p) % p;
for (int i = 2; i <= k; i++){
ans = ans * i % p;
}
cout << "Case #" << cs << ": " << ans % p << '\n';
}
}
CF115D Unambiguous Arithmetic Expression
原题链接:Unambiguous Arithmetic Expression
分析
和我想的也差不多吧,类似一个递归,就是说,你会发现,一坨符号会影响之后的一坨数。
也不全对。我场上看出来了...... 40 % 40\% 40%?
就是说,一旦出现 * / 相连就完蛋了。然后,对于一段 + - * /,第一个是二元的,其他都是一元的......反正就是这个意思吧,你懂的。
就是 * / 不能做单元的运算符。
我们来设一个非常神奇的 DP 式子,我们设 d p i , j dp_{i,j} dpi,j 表示填完前 i i i 个字符后的括号,多出 j j j 个左括号的方案数。
???
换句话说不就是要消耗 j j j 个双元吗?
考虑一边完全可以兼顾另外一边,所以,非常完美。
那么,转移完全是容易的,直接:
d p i , j = ∑ k = j i d p i − 1 , k dp_{i,j}=\sum\limits_{k=j}^{i}{dp_{i-1,k}} dpi,j=k=j∑idpi−1,k
正解
cpp
#include <bits/stdc++.h>
#define int long long
#define mod 1000003
using namespace std;
const int N = 2005;
string s;
int dp[N][N];
int n, a[N];
signed main(){
freopen("expression.in", "r", stdin);
freopen("expression.out", "w", stdout);
cin >> s;
int m = 0;
for (int i = 0; i < (int)s.length(); i++){
if (s[i] == '*' || s[i] == '/'){
a[++m] = 1;
}
else if (s[i] == '+' || s[i] == '-'){
a[++m] = 3;
}
else if (s[i] >= '0' && s[i] <= '9'){
while (i + 1 < (int)s.length() && s[i + 1] >= '0' && s[i + 1] <= '9')
i++;
a[++m] = 2;
}
}
n = m;
for (int i = 1; i <= n; i++){
if (a[i] == 1 && a[i - 1] != 2){
cout << 0;
return 0;
}
}
dp[0][0] = 1;
for (int i = 1; i <= n; i++){
if (a[i] != 2)
for (int j = 1; j <= n; j++){
dp[i][j] = dp[i - 1][j - 1];
}
else{
for (int j = n; j >= 0; j--){
dp[i][j] = (dp[i - 1][j] + dp[i][j + 1]) % mod;
}
}
}
cout << dp[n][0];
}
CF2183F Jumping Man
原题链接:Jumping Man
分析
哦,我是不是没看懂这题的题面?那不补了!
LGP17427 ICPC 2018 Xuzhou R Rikka with An Unnamed Temple
原题链接:ICPC 2018 Xuzhou R Rikka with An Unnamed Temple
分析
我的暴力,我的 110 p t s 110pts 110pts😭
我们来学一下这个图上的 DP 吧。