A
题意:让我们找到1~n中所有只有一位是非0数的个数。
思路:比较简单直接上代码
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 1e6 + 10;
int a[N];
bool f(int x)
{
int sum = 0;
while (x)
{
int k = x % 10;
if (k > 0)
sum++;
x /= 10;
}
if (sum == 1)
return true;
return false;
}
void solve()
{
int n;
cin >> n;
cout << a[n] << endl;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int T;
cin >> T;
for (int i = 1; i <= 1000000; i++)
{
if (f(i))
a[i] = a[i - 1] + 1;
else
a[i] = a[i - 1];
}
while (T--)
{
solve();
}
return 0;
}
B
题意:给我们由n个字符组成的字符串,我们可以进行一个操作就是一个字符一个字符(任意字符)的插入,和把前面相邻的已经插入的k个字符复制一下插到结尾,问我们能不能在小于n次操作中得到给出的字符串。
思路:就是找一下有没有相同的子串。注意三个完全相同的要特殊处理一下。
#include <cstring>
#include <iostream>
#include <algorithm>
#include <unordered_map>
using namespace std;
unordered_map<string, bool> mp;
void solve()
{
mp.clear();
int n;
cin >> n;
string s;
cin >> s;
for (int i = 0; i < (int)s.size() - 1; i++)
{
string ss = s.substr(i, 2);
if (s[i] == s[i + 1] && s[i - 1] == s[i] && s[i + 2] != s[i])
continue;
if (mp[ss])
{
cout << "YES" << endl;
return;
}
mp[ss] = true;
}
cout << "NO" << endl;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int T;
cin >> T;
while (T--)
{
solve();
}
return 0;
}
C
题意:给我们只有两个由W和B组成的字符串,然后每一列至少有一个“B”,问我们在不能走重复的点并且只走B的情况下,能不能把所有的B都走到。
思路:我们模拟一下并且计数比较一下即可。
#include <cstring>
#include <iostream>
#include <algorithm>
#include <queue>
using namespace std;
const int N = 2e5 + 10;
int n;
char s[3][N];
bool st[3][N];
int nex, ney, nowx, nowy;
int dx[4] = {0, 0, 0, 1};
int dy[4] = {0, 1, -1, 0};
int bfs(int x, int y)
{
int sum = 1;
st[x][y] = true;
while (true)
{
int k = false;
if (y > n)
{
return sum;
}
if (x == 1)
{
if (s[2][y] == 'B' && st[2][y] == false)
{
st[2][y] = true;
x = 2;
sum++;
k = true;
}
else if (s[x][y + 1] == 'B' && st[x][y + 1] == false)
{
st[x][y + 1] = true;
y = y + 1;
sum++;
k = true;
}
}
else if (x == 2)
{
if (s[1][y] == 'B' && st[1][y] == false)
{
st[1][y] = true;
x = 1;
sum++;
k = true;
}
else if (s[x][y + 1] == 'B' && st[x][y + 1] == false)
{
st[x][y + 1] = true;
y = y + 1;
sum++;
k = true;
}
}
if (k == false)
{
break;
}
}
return sum;
}
void solve()
{
cin >> n;
for (int i = 1; i <= 2; i++)
{
cin >> s[i] + 1;
}
int cnt = 0;
for (int i = 1; i <= 2; i++)
{
for (int j = 1; j <= n; j++)
{
if (s[i][j] == 'B')
cnt++;
}
}
if (n == 1)
{
cout << "YES" << endl;
}
else
{
memset(st, false, sizeof st);
int flag = 0;
if (s[1][1] == 'B')
{
int sum = bfs(1, 1);
if (sum == cnt)
{
cout << "YES" << endl;
return;
}
}
memset(st, false, sizeof st);
if (s[2][1] == 'B')
{
int sum = bfs(2, 1);
if (sum == cnt)
{
cout << "YES" << endl;
return;
}
}
cout << "NO" << endl;
}
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int T;
cin >> T;
while (T--)
{
solve();
}
return 0;
}
D
题意 :给我们两个数x和y问我们把他们同时加上1使他们gcd(x,y)=1最大可以加几次。
思路:本题我们可以证明出
g
c
d
(
x
+
k
,
y
+
k
)
=
g
c
d
(
x
+
k
,
y
−
x
)
gcd(x+k,y+k) = gcd(x+k,y-x)
gcd(x+k,y+k)=gcd(x+k,y−x) 如果对此有疑问的话可以看一下官方题解讲的非常的详细也很好理解(传送门)然后我们得到上面的结论之后我们就可以求出(y-x)的质因数,然后所有质因数的倍数>x的那个并且是最小的我们设N,然后N-x就是我们的答案。
这个题求质因数的方法值得学习
#include <cstring>
#include <iostream>
#include <algorithm>
#include <vector>
#include <cmath>
using namespace std;
const int N = 1e7 + 10;
int a[N];
int mind[N];
vector<int> v;
void init()
{
for (int i = 0; i < N; i++)
mind[i] = i;
for (int i = 2; i < N; i++)
{
if (mind[i] != i)
continue;
for (int j = 2 * i; j < N; j += i)
mind[j] = min(mind[j], i);
}
}
void divide(int x)
{
while (x > 1)
{
if (v.empty() || v.back() != mind[x])
v.push_back(mind[x]);
x /= mind[x];
}
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
init();
int T;
cin >> T;
while (T--)
{
int n, m;
cin >> n >> m;
if (__gcd(n, m) != 1)
{
cout << 0 << endl;
}
else
{
if (abs(m - n) == 1)
{
cout << -1 << endl;
}
else
{
int x = abs(m - n);
divide(x);
int ans = 0x3f3f3f3f;
int tem;
for (int i = 0; i < v.size(); i++)
{
tem = (int)ceil(n * 1.0 / v[i]);
ans = min(ans, tem * v[i] - n);
}
cout << ans << endl;
v.clear();
}
}
}
return 0;
}