题目大意:给出一个数n和一个100位以内的n进制数s,每步操作令s=s+s的头尾翻转,问30步操作内最少多少步能将s变成一个回文数
2<=n<=10或n=16
思路:因为最多只有30步,100位数,所以模拟的时间复杂度肯定够,直接上高精度非10进制加法运算模板
- //#include<__msvc_all_public_headers.hpp>
- #include
- using namespace std;
- typedef long long ll;
- const int N = 3e5+ 5;
- const ll MOD = 998244353;
- int n;
- bool check(string x)
- {//检查是否是回文数
- string y = x;
- reverse(y.begin(), y.end());
- return y == x;
- }
- void init()
- {
-
- }
- string add(string x1, string x2,int d)
- {//高精度d进制加法
- string ret;
- int l = x1.length();//本题中两数位数相同
- int pre = 0;
- for (int i = l - 1; i >= 0; i--)
- {//从后向前逐位遍历
- int x = x1[i] - '0' + x2[i] - '0' + pre;//当前位的和加上进位
- if (d == 16)
- {
- if (x1[i] >= 'A' && x1[i] <= 'F')
- {//16进制的字母要单独处理
- x -= x1[i] - '0';
- x += x1[i] - 'A' + 10;
- }
- if (x2[i] >= 'A' && x2[i] <= 'F')
- {
- x -= x2[i] - '0';
- x += x2[i] - 'A' + 10;
- }
- }
- pre = x / d;//进位
- x = x % d;//当前位的数
- if (d == 16)
- {
- if (x >= 10)
- {
- ret += 'A' + x - 10;
- continue;
- }
- }
- ret += '0' + x;//先放到最后一位
- }
- if (pre)
- {//处理最后的进位
- if (d == 16 && pre >= 10)
- {
- ret += 'A' + pre - 10;
- }
- else
- ret += '0' + pre;
- }
- reverse(ret.begin(), ret.end());//最后再把整个倒过来
- return ret;
- }
- void solve()
- {
- cin >> n;
- init();
- string s;
- cin >> s;
- int cnt = 0;
- while (cnt <= 30)
- {
- if (check(s))
- {
- cout << "STEP=" << cnt << '\n';
- return;
- }
- cnt++;
- string s2 = s;
- reverse(s2.begin(), s2.end());
- s = add(s, s2, n);
- //cout << s << '\n';
- }
- cout << "Impossible!";
- cout << '\n';
- }
- int main()
- {
- ios::sync_with_stdio(false);
- cin.tie(0);
- int t;
- t=1;
- // cin>>t;
- while (t--)
- {
- solve();
- }
- return 0;
- }