2023ICPC沈阳 M题 Outro: True Love Waits
-
3 mins read
题意
有一张无限大的图,每个整数都对应图上一个点。对两个整数,如果二进制仅有第i位不同,则它们有一条权重为i的边相连。 在图上移动时,规则是从目前所在点,走过权重最小的边到达下一个点,然后把这条边删掉。 输入s,t (二进制表示,长度<=1e6)和k,问若以s为起点,可否第k次到达t点?那时走了几步? 对1e9+7取模。
分析及实现
手推规律后,发现有循环性。如下图:
代码
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define endl '\n'
typedef unsigned long long ull;
const int N = 1e5;
const int INF = 0x3f3f3f3f3f3f3f3f;
const int MOD = 1e9 + 7;
int qpow(int x, int k)
{
int ret = 1;
x %= MOD;
while (k)
{
if (k & 1)
{
ret *= x;
ret %= MOD;
}
x *= x;
x %= MOD;
k >>= 1;
}
return ret;
}
int inv(int x, int mod)
{
return qpow(x, mod - 2);
}
map<int, int> mp;
void solve()
{
string s, t;
int k;
cin >> s >> t >> k;
if (t == s) /////
{
int INV = inv(3, MOD);
int b1 = (1 + INV) % MOD;
int ans = b1 * qpow(4, k - 1) % MOD;
ans -= 1;
ans += MOD;
ans %= MOD;
ans -= INV;
ans += MOD;
ans %= MOD;
cout << ans << endl;
return;
}
if (s.length() < t.length())
{
swap(s, t);
}
int n = s.length();
int m = t.length();
for (int i = m - 1; i >= 0; --i)
{
int j = i - m + n;
s[j] = '0' + (s[j] - '0') ^ (t[i] - '0');
}
// s
if (s.length() % 2 != 0)
{
s = "0" + s;
} // 0123
// cout << "s " << s << endl;
int fir = 0;
int base = 1;
for (int i = s.length() - 1; i > 0; i -= 2)
{
int num = (s[i - 1] - '0') * 2 + s[i] - '0';
if (i == s.length() - 1)
{
fir += (mp[num]) * base % MOD;
}
else
fir += (mp[num] - 1) * base % MOD;
fir %= MOD;
base = (base * 4 + 1) % MOD;
}
fir -= 1;
fir += MOD;
fir %= MOD;
// cout << "fir " << fir << endl;
int cnt00 = 0;
for (int i = s.length() - 1; i > 0; i-=2)
{
if (s[i] == '0' && s[i - 1] == '0')
{
cnt00++;
}
if(s[i]=='1'||s[i-1]=='1')
{
break;
}
}
if (1 + cnt00 < k)
{
cout << -1 << endl;
return;
}
int INV = inv(3, MOD);
int b1 = (1 + INV) % MOD;
int ans = b1 * qpow(4, k - 1) % MOD; // add
ans -= 1;
ans += MOD;
ans %= MOD;
ans -= INV;
ans += MOD;
ans %= MOD;
ans += fir;
ans %= MOD;
cout << ans << endl;
}
signed main()
{
// cout.flags(ios::fixed); cout.precision(8);
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
mp[0] = 1;
mp[1] = 2;
mp[3] = 3;
mp[2] = 4;
int T = 1;
cin >> T;
for (int i = 1; i <= T; ++i)
{
solve();
}
return 0;
}
/*
*/