1700 相似颜色
模拟 + 暴力,随便搞一搞就好了
#define others
#ifdef others
#include <iostream>
#include <cstring>
#include <cmath>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <string>
#include <map>
#include <set>
#endif // poj
#ifdef others
#include <bits/stdc++.h>
#endif // others
//#define file
//#define time
#define all(x) x.begin(), x.end()
using namespace std;
const double eps = 1e-8;
const double pi = acos(-1.0);
int dcmp(double x) {
if(fabs(x)<=eps) return 0;
return (x>0)?1:-1;
};
typedef long long LL;
typedef unsigned long long ULL;
void umax(int &a, int b) {
a = max(a, b);
}
void umin(int &a, int b) {
a = min(a, b);
}
void file() {
freopen("pe.in", "r", stdin);
// freopen("1.txt", "w", stdout);
}
/*
dp[i] = sigma(C(i, i-j)/(2^i) * (1 + dp[j]));
*/
namespace Solver {
string str;
LL cov1(char c) {
if(isalpha(c)) return c - 'a' + 10;
else return c - '0';
}
char cov2(LL c) {
if(c <= 9) return '0' + c;
else return c-10+'a';
}
struct A {
LL ans;
LL a, b, c;
};
LL cal(string s, string t) {
LL sum = 0;
for(int i = 1; i < 6; i+=2) {
sum += (cov1(s[0+i])*16+cov1(s[i+1]) - (cov1(t[i+0])*16+cov1(t[i+1])))*(cov1(s[0+i])*16+cov1(s[i+1]) - (cov1(t[i+0])*16+cov1(t[i+1])));
}
return sum;
}
void solve() {
cin >> str;
A ans = {1e18, 0, 0, 0};
for(LL i = 0; i <= 16; i++)
for(LL j = 0; j <= 16; j++)
for(LL k = 0; k <= 16; k++) {
string tmp = "#";
tmp += cov2(i);
tmp += cov2(i);
tmp += cov2(j);
tmp += cov2(j);
tmp += cov2(k);
tmp += cov2(k);
if(cal(str, tmp) < ans.ans) {
ans.ans = cal(str, tmp);
// cout<<i<<" "<<j<<" "<<k<<endl;
ans.a = i, ans.b = j, ans.c = k;
}
}
putchar('#');
printf("%c%c%c", cov2(ans.a), cov2(ans.b), cov2(ans.c));
}
}
int main() {
// file();
Solver::solve();
#ifdef time
printf("Time = %.5f ms", (double)clock()/CLOCKS_PER_SEC);
#endif // time
return 0;
}
1701 挑选子集
简单的计数问题。
首先从N个数挑出M个数,每个数两两的差都为K的倍数,等价于这些数模K同余。
因此按模K的余数进行分组,随后每组单独计数即可。
#define others
#ifdef others
#include <iostream>
#include <cstring>
#include <cmath>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <string>
#include <map>
#include <set>
#endif // poj
#ifdef others
#include <bits/stdc++.h>
#endif // others
//#define file
//#define time
#define all(x) x.begin(), x.end()
using namespace std;
const double eps = 1e-8;
const double pi = acos(-1.0);
int dcmp(double x) {
if(fabs(x)<=eps) return 0;
return (x>0)?1:-1;
};
typedef long long LL;
typedef unsigned long long ULL;
void umax(int &a, int b) {
a = max(a, b);
}
void umin(int &a, int b) {
a = min(a, b);
}
void file() {
freopen("pe.in", "r", stdin);
// freopen("1.txt", "w", stdout);
}
/*
dp[i] = sigma(C(i, i-j)/(2^i) * (1 + dp[j]));
*/
namespace Solver {
int n, m, k;
int v[111];
LL C[111][111];
const LL mod = 1000000009;
void solve() {
C[0][0] = C[1][0] = C[1][1] = 1;
for(int i = 2; i < 111; i++) {
C[i][0] = C[i][i] = 1;
for(int j = 1; j < i; j++)
C[i][j] = C[i-1][j-1] + C[i-1][j] % mod;
}
scanf("%d%d%d", &n, &m, &k);
for(int i = 1; i <= n; i++) {
int val;
scanf("%d", &val);
v[val%k]++;
}
LL res = 0;
for(int i = 0; i <= k; i++) {
if(v[i] >= m)
res += C[v[i]][m];
res %= mod;
}
cout<<res;
};
}
int main() {
// file();
Solver::solve();
#ifdef time
printf("Time = %.5f ms", (double)clock()/CLOCKS_PER_SEC);
#endif // time
return 0;
}
1702 矩阵迷宫
走方格最小化问题,加两维分别表示当前的方向和已经转向的次数,然后正常DP即可。
#define others
#ifdef others
#include <iostream>
#include <cstring>
#include <cmath>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <string>
#include <map>
#include <set>
#endif // poj
#ifdef others
#include <bits/stdc++.h>
#endif // others
//#define file
//#define time
#define all(x) x.begin(), x.end()
using namespace std;
const double eps = 1e-8;
const double pi = acos(-1.0);
int dcmp(double x) {
if(fabs(x)<=eps) return 0;
return (x>0)?1:-1;
};
typedef long long LL;
typedef unsigned long long ULL;
void umax(LL &a, LL b) {
a = max(a, b);
}
void umin(LL &a, LL b) {
a = min(a, b);
}
void file() {
freopen("pe.in", "r", stdin);
// freopen("1.txt", "w", stdout);
}
/*
dp[i] = sigma(C(i, i-j)/(2^i) * (1 + dp[j]));
*/
namespace Solver {
LL n;
LL v[111][111];
LL dp[111][111][2][30];
LL cost[33];
void solve() {
for(LL i = 0; i <= 30; i++) cost[i] = 1LL<<(i-1);
scanf("%lld", &n);
for(LL i = 0; i < 111; i++)
for(LL j = 0; j < 111; j++)
for(LL k = 0; k < 30; k++)
dp[i][j][0][k] = dp[i][j][1][k] = 1e18;
for(LL i = 1; i <= n; i++)
for(LL j = 1; j <= n; j++)
scanf("%lld", &v[i][j]);
for(int i = 0; i < 2; i++)
for(int j = 0; j < 30; j++)
dp[1][1][i][j] = v[1][1];
for(LL i = 1; i <= n; i++) {
for(LL j = 1; j <= n; j++) {
if(i == j && i == 1) continue;
for(LL k = 0; k <= 1; k++) {
for(LL p = 0; p < 30; p++) {
if(i >= 2 && k == 0) {
umin(dp[i][j][k][p], dp[i-1][j][k][p] + v[i][j]);
} else if(j >= 2 && k == 1) {
umin(dp[i][j][k][p], dp[i][j-1][k][p] + v[i][j]);
}
if(p != 0 && k == 1 && j >= 2) {
umin(dp[i][j][k][p], dp[i][j-1][0][p-1] + v[i][j] + cost[p]);
} else if(p != 0 && k == 0 && i >= 2) {
umin(dp[i][j][k][p], dp[i-1][j][1][p-1] + v[i][j] + cost[p]);
}
}
}
// LL ans = 1e18;
// for(LL k = 0; k < 30; k++)
// ans = min(ans, dp[i][j][0][k]), ans = min(ans, dp[i][j][1][k]);
// cout<<ans<<" i = "<<i<<" j = "<<j<<endl;
}
}
LL ans = 1e18;
for(LL i = 0; i < 30; i++)
ans = min(ans, dp[n][n][0][i]), ans = min(ans, dp[n][n][1][i]);
cout<<ans;
}
}
int main() {
// file();
Solver::solve();
#ifdef time
printf("Time = %.5f ms", (double)clock()/CLOCKS_PER_SEC);
#endif // time
return 0;
}
1703 比赛的时候不会,赛后看别人代码恍然大悟。
给出中序遍历,问字典序第
k
大的前序遍历是多少。
二叉树的方案数就是括号序列的种类数,也就是卡特兰数,因此
给出的是中序遍历,那么我们可以枚举根,然后在根的左边枚举左子树,根的右边枚举右子树。
假设当前根的左边有
x
个未确认点,右边有
因此我们可以先把所有数从小到大排序,枚举根,就可以逐渐缩小k,当确定了左右子树的时候,再递归下去解决即可,因为要求的是前序遍历,需要注意下统计答案的顺序。
#define others
#ifdef poj
#include <iostream>
#include <cstring>
#include <cmath>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <string>
#include <map>
#include <set>
#endif // poj
#ifdef others
#include <bits/stdc++.h>
#endif // others
//#define file
#define all(x) x.begin(), x.end()
using namespace std;
const double pi = acos(-1.0);
typedef long long LL;
typedef unsigned long long ULL;
void umax(int &a, int b) {
a = max(a, b);
}
void umin(int &a, int b) {
a = min(a, b);
}
void file() {
freopen("a.in", "r", stdin);
// freopen("1.txt", "w", stdout);
}
namespace Solver {
LL n, k;
const LL maxn = 33;
LL T[maxn];
LL v[maxn];
vector<LL> G;
void dfs(LL l, LL r, LL t) {
if(l > r) return ;
if(l == r) {
G.push_back(v[l]);
return ;
}
vector<pair<LL, LL>>vec;
for(LL i = l; i <= r; i++) vec.push_back({v[i], i});
sort(all(vec));
for(LL i = 0; i < vec.size(); i++) {
LL pos = vec[i].second;
LL tmp = T[pos - l] * T[r - pos];
if(tmp >= t) {
G.push_back(v[pos]);
dfs(l, pos-1, (t-1)/T[r-pos]+1);
dfs(pos+1, r, (t-1)%T[r-pos]+1);
break;
} else t -= tmp;
}
}
void solve() {
T[0] = T[1] = 1;
for(LL i = 2; i < maxn; i++) {
for(LL j = 0; j < i; j++)
T[i] += T[j] * T[i-j-1];
}
scanf("%lld%lld", &n, &k);
for(LL i = 1; i <= n; i++) scanf("%lld", &v[i]);
dfs(1, n, k);
for(auto v:G) printf("%lld\n", v);
}
};
int main() {
// file();
Solver::solve();
return 0;
}