菜是原罪
A
题意
给出两串二进制数,将第二串乘上2^k之后把两串按二进制加起来反转,问k取多少使得结果呈字典序最小。
题解
想要反转后字典序最小,也就是把第二串最后1个1的位置与第一串相对应,将其向右移动多少位使得这两个1能对应,(两个1相加时消去变下一位)。
#include <iostream> #include <cstring> #include <string> #include <algorithm> #include <cmath> #include <cstdio> #include <queue> #include <stack> #include <map> #define ull unsigned long long #define met(a, b) memset(a, b, sizeof(a)) #define lowbit(x) (x&(-x)) #define MID (l + r) / 2 #define ll long long #define cinint(a) scanf("%d", &a) #define cinll(a) scanf("%lld", &a) #define cindouble(a) scanf("%lf", &a) #define cinstr(a) scanf(" %s", a) #define coutint(a) printf("%d ", a) #define coutll(a) printf("%lld ", a) #define coutdouble(a) printf("%lf ", a) using namespace std; const int maxn = 1e5 + 7; const ll mod = 1e6 + 3; const int inf = 0x3f3f3f3f; const ll INF = 0x3f3f3f3f3f3f3f3f; int main() { int T; cin >> T; while(T--) { string str1, str2; cin >> str1 >> str2; int len1 = str1.size(); int len2 = str2.size(); int i = len1 - 1, j = len2 - 1; while(str2[j] != '1') i--, j--; while(str1[i] != '1') i--; cout << len1 - i - len2 + j << endl; } return 0; }
B
题意
有一种只有两个按键的计算器,一个增加x,一个增加y。现在给出一串数字,问在以(x, y)(0 <= x, y <= 10)为基础时,最少要添加多少个数使得这一串数字可以被这种计算器输出出来
题解
想要使得一串数字成立,也就是去看在串中每两个数字之间需要放入多少个数,那我们可以提前用最短路去处理出任意两个数字在(x, y)(0 <= x, y <= 10)时,从x到y最少需要多少个数,之后暴力去查询就好了。
#include <iostream> #include <cstring> #include <string> #include <algorithm> #include <cmath> #include <cstdio> #include <queue> #include <stack> #include <map> #define ull unsigned long long #define ll long long #define met(a, b) memset(a, b, sizeof(a)) #define lowbit(x) (x&(-x)) #define MID (l + r) / 2 using namespace std; const int mod = 3e7; const int inf = 0x3f3f3f3f; const ll INF = 0x3f3f3f3f3f3f3f3f; const int maxn = 5e3 + 7; int dp[11][11][11][11]; queue<int> que; void cal(int i, int j) { for(int s = 0; s < 10; s++) { while(!que.empty()) que.pop(); dp[i][j][s][(s+i) % 10] = dp[i][j][s][(s+j) % 10] = 1; que.push((s+i) % 10); que.push((s+j) % 10); while(!que.empty()) { int t = que.front(); que.pop(); if(dp[i][j][s][(t+i) % 10] == -1) { dp[i][j][s][(t+i) % 10] = dp[i][j][s][t] + 1; que.push((t+i) % 10); } if(dp[i][j][s][(t+j) % 10] == -1) { dp[i][j][s][(t+j) % 10] = dp[i][j][s][t] + 1; que.push((t+j) % 10); } } } } int cnt[11][11]; int main() { met(dp, -1); for(int i = 0; i < 10; i++) { for(int j = 0; j < 10; j++) { cal(i, j); } } string str; cin >> str; for(int i = 1; i < str.size(); i++) ++cnt[str[i-1] - '0'][str[i] - '0']; for(int i = 0; i < 10; i++) { for(int j = 0; j < 10; j++) { int flag = 1; ll res = 0; for(int s = 0; s < 10 && flag; s++) { for(int e = 0; e < 10 && flag; e++) { if(!cnt[s][e]) continue; if(dp[i][j][s][e] == -1) { flag = 0; res = -1; break; } res += cnt[s][e]*(dp[i][j][s][e] - 1); } } cout << res << ' '; } cout << endl; } return 0; }
D
题意
给出n,让你给出一个串,使得其中子序列为“1337”的有n个。
题解
将串都写作1333……1111……337的格式就好了,前面的一个1和后面的37可以组成的个数取决于3也就是(C_m^2)个,后面的一串1与后面的37组成的个数取决于1的个数。
#include <iostream> #include <cstring> #include <string> #include <algorithm> #include <cmath> #include <cstdio> #include <queue> #include <stack> #include <map> #define ull unsigned long long #define ll long long #define met(a, b) memset(a, b, sizeof(a)) #define lowbit(x) (x&(-x)) #define MID (l + r) / 2 using namespace std; const int mod = 3e7; const int inf = 0x3f3f3f3f; const ll INF = 0x3f3f3f3f3f3f3f3f; const int maxn = 5e3 + 7; int main() { int T; cin >> T; while(T--) { int n; cin >> n; int t = 2; while((t-1)*t/2 <= n) ++t; --t; cout << "1"; for(int i = 1; i <= t-2; i++) cout << "3"; t = n - (t-1)*t/2; for(int i = 1; i <= t; i++) cout << "1"; cout << "337" << endl; } return 0; }