A 题目链接:Problem - A - Codeforces
input:
5
9
42
13
100
111
output:
9
13
10
19
19
题意:
给定一个数 n ,求 1 ~ n 之间有多少个数,满足只有一位非0.
思路:
既然只有一位非0,那么一定是首位非0,直接计算,计算方式就是 n 的位数减1 * 9,加上 n 的最高位即可。
代码如下:
#pragma GCC optimize(3)
#include<bits/stdc++.h>
#define endl "\n"
using namespace std;
typedef long long ll;
const int mod=1e9+7;
const int N=2e5+10;
int t,n;
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin>>t;
while(t--)
{
cin>>n;
int ans=0;
while(n>10)
{
ans+=9;
n/=10;
}
cout<<ans+n<<endl;
}
return 0;
}
B 题目链接:Problem - B - Codeforces
input:
6
10
codeforces
8
labacaba
5
uohhh
16
isthissuffixtree
1
x
4
momo
output:
NO
YES
NO
YES
NO
YES
题意:
给定一个长度为 n 字符串,试用以下两种操作构造该字符串:
1.在当前构造中的字符串尾添加一个字符。
2.从当前构造中的字符串中,复制任意一个连续段,添加到字符串尾。
问能否使用 n 次以内操作构造出目标字符串。
思路:
小于 n 次操作,意味着我们至少要使用一次操作2,复制至少两个字符。故我们直接以长度为2的滑动窗口遍历字符串,将所有遍历结果全都放进 map 里,看是否存在两个子串相等并且位置相距超过 1 的情况(比如 nnn 这一串,虽然12 和 23 都是 nn,但是并不能直接复制完成目标,因为中间的 n 是共用的,所以必须满足间隔超过1)。
代码如下:
#pragma GCC optimize(3)
#include<bits/stdc++.h>
#define endl "\n"
using namespace std;
typedef long long ll;
const int mod=1e9+7;
const int N=2e5+10;
int t,n;
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin>>t;
while(t--)
{
cin>>n;
string s;
cin>>s;
map<string,int> mp;
bool f=0;
for(int i=0;i<n-1;i++)
{
string k=s.substr(i,2);
// cout<<k<<endl;
if(!mp.count(k))
mp[k]=i;
else
{
if(i-mp[k]>1)
{
f=1;
break;
}
}
}
if(f)
cout<<"YES"<<endl;
else
cout<<"NO"<<endl;
}
return 0;
}
C 题目链接:Problem - C - Codeforces
input:
6
3
WBB
BBW
1
B
B
5
BWBWB
BBBBB
2
BW
WB
5
BBBBW
BWBBB
6
BWBBWB
BBBBBB
output:
YES
YES
NO
NO
NO
YES
题意:
给定一个 2 * m 的格子矩形,每个格子上 "B" 代表涂黑,"W"代表不涂黑,为白色。现给出该矩形的涂色方案,问是否有一条通路满足以下两点:
1.该通路经过所有涂黑格子,且只经过一次。
2.该通路上没有任何白色格子。
思路:
两次 dfs 遍历,dfs 中对经过的黑色格子进行计数,dfs 结束后判断计数结果是否等于整个矩形黑色格子的数量。
dfs 的优先级是优先上下走,其次左右走(注意两次 memset vis 数组)
代码如下:
#pragma GCC optimize(3)
#include<bits/stdc++.h>
#define endl "\n"
using namespace std;
typedef long long ll;
const int mod=1e9+7;
const int N=2e5+10;
char c[4][N];
bool vis[4][N];
int t,n;
int func(int x,int y)
{
vis[x][y]=1;
if(c[3-x][y]=='B'&&!vis[3-x][y])
return func(3-x,y)+1;
if(y!=n&&c[x][y+1]=='B'&&!vis[x][y+1])
return func(x,y+1)+1;
return 1;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin>>t;
while(t--)
{
cin>>n;
int cnt=0;
for(int i=1;i<=2;i++)
{
for(int j=1;j<=n;j++)
{
cin>>c[i][j];
if(c[i][j]=='B')
++cnt;
vis[i][j]=0;
}
}
bool f=0;
if(c[1][1]=='B'&&func(1,1)==cnt)
f=1;
for(int i=1;i<=2;i++)
{
for(int j=1;j<=n;j++)
{
vis[i][j]=0;
}
}
if(c[2][1]=='B'&&func(2,1)==cnt)
f=1;
if(f)
cout<<"YES"<<endl;
else
cout<<"NO"<<endl;
}
return 0;
}
D 题目链接:Problem - D - Codeforces
input:
4
5 15
13 37
8 9
10009 20000
output:
0
1
-1
79
题意:
一对数x,y称为 lucky ,当该对数满足 gcd (x , y) == 1。
定义 (x , y) , (x + 1, y + 1) , (x + 2, y + 2) , (x + 3, y + 3) , ...... , (x + k, y + k) 为长度 k + 1 的数对链,当该链上所有数对都为 lucky 时,称该数对链为 lucky。
给定一个数 n ,对于 n 组 x ,y,问以数对 (x , y) 为开头的 lucky 数对链的长度最大是多少。
思路:
首先引入一个重要的结论:gcd (x , y) == gcd (x , abs (x - y))
由此可以推出:gcd (x + k , y + k) == gcd (x + k, abs (x - y))
所以令 d = abs (x - y),我们需要找到最小 k ,使 gcd (x + k, d) != 1 即可。
如何满足上述式子,只需要 x + k 成为某个 d 的质因数的倍数即可,所以我们对 d 分解质因数,然后对于质因数 a ,维护 a - x % a 最小值即可。
询问外预处理 1e7 内的数,为质数或非质数,之后询问时使用。
代码如下:
#pragma GCC optimize(3)
#include<bits/stdc++.h>
#define endl "\n"
using namespace std;
typedef long long ll;
const int mod=1e9+7;
const int N=1e7+10;
int t,n;
int p[N];
int prime[N];
int ind=0;
void prime_2()
{
for(int i=2;i<=1E7;i++)
{
if(!p[i])
{
prime[++ind]=i;
p[i]=i;
}
for(int j=1;j<=ind;j++)
{
if(i*prime[j]>1E7) break;
p[i*prime[j]]=prime[j];
if(i%prime[j]==0) break;
}
}
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
prime_2();
cin>>t;
while(t--)
{
int x,y;
cin>>x>>y;
int d=y-x;
vector<int> v;
if(d==1)
{
cout<<-1<<endl;
continue;
}
if(__gcd(x,y)!=1)
{
cout<<0<<endl;
continue;
}
int ans=10*N;
while(d>1)
{
ans=min(ans,p[d]-x%p[d]);
d/=p[d];
}
cout<<ans<<endl;
}
return 0;
}