Educational Codeforces Round 139 (Rated for Div. 2)
A. Extremely Round
----------------------------------题解-------------------------------------
因为数据范围只有1e6,我们只需要预处理出来1-1e6每个每个数包含多少个极圆整数就行了,然后t次查询就可以。这种预处理查询是面对多次询问时应该首先想到的。
点击查看代码
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+10;
int a[N];
int main()
{
int t;
cin>>t;
for(int i=1;i<=N;i++)
{ int w=i;
int cnt=0;
while(w!=0)
{
if(w%10!=0) cnt++;
w=w/10;
}
if(cnt==1) a[i]=a[i-1]+1;
else a[i]=a[i-1];
}
while(t--)
{
int n;
cin>>n;
cout<<a[n]<<'\n';
}
}
B. Notepad#
有两种操作,第一种是直接在末尾添加,第二种是复制一段连续的到末尾,如果都采用第一步需要n次,问你能不能剩下步数采用k<n次
-----------------------------------------------------题解--------------------------------------------------
由上述性质可知我们可以,只要我们能找到一个长度为2或者更大的子串在前面出现过,(其实为2就可以),那么最后的答案就是yes,我们便利一整个字符串的i和i+1,并用一个map<string,int>把他们存起来,如果找到一个子串c为m[c]>=2就最后输出yes,特别的为了防止aaa这种三连的情况,我们要在遍历到a[i]a[i+1]a[i+2]的时候 让i跳过一个
这样既可以跳过aaa又不会错过aaaa
点击查看代码
#include<bits/stdc++.h>
using namespace std;
const int N=2e5+10;
int main()
{
int t;
cin>>t;
while(t--)
{
int n;
cin>>n;
string a;
cin>>a;
int cnt=0;
int jud=0;
map<string,int>m;
for(int i=0;i<n-1;i++)
{
string c="";
c+=a[i];
c+=a[i+1];
//cout<<c<<endl;
m[c]++;
if(a[i+2]==a[i]&&a[i+1]==a[i]) i++;
}
for(int i=0;i<n-1;i++)
{ string c="";
c+=a[i];
c+=a[i+1];
// cout<<c<<endl;
// cout<<c<<" "<<m[c]<<'\n';
if(m[c]>=2) jud=1;
if(a[i+2]==a[i]&&a[i+1]==a[i]) i++;
}
if(jud==1) cout<<"YES"<<'\n';
else cout<<"NO"<<'\n';
}
}
C. Hamiltonian Wall
题意:不走重复的格子,能不能把所有B格子走完
------------------------------题解-------------------------------------
这题可以爆搜,但我更喜欢快刀斩乱麻。经过我的思考和观察我发现,除去中间有(W,W)隔断以外,有两种情况是刷不完的(W,R)与(W,R)和(R,w)与(R,w)所包含的(B,B)列如果是奇数,就一定会漏掉一个,同理,(W,R)和(R,W)所夹着(B,B)列如果是偶数,就一定也刷不完。知道这个关键点这道题就容易很多了,我们只需要枚举字符串中每一个不是(B,B)的列,然后观察他和前一个不是(B,B)列的关系,然后在判断他俩中间夹着的(B,B)列的数量就可以了
点击查看代码
#include<bits/stdc++.h>
using namespace std;
const int N=2e5+10;
char a[4][N];
pair<int,int> p[N];
int main()
{
int t;
cin>>t;
while(t--)
{
int n;
cin>>n;
for(int i=1;i<=2;i++)
{
for(int j=1;j<=n;j++)
{
cin>>a[i][j];
}
}
int q=0;
int jud=0;
for(int i=1;i<=n;i++)
{
if(a[1][i]=='B'&&a[2][i]=='W')
{
q++;
p[q].first=1,p[q].second=i;
}
else if(a[1][i]=='W'&&a[2][i]=='B')
{
q++;
p[q].first=2,p[q].second=i;
}
else if(a[1][i]=='W'&&a[2][i]=='W') jud=1;
}
for(int i=1;i<=q-1;i++)
{
if((p[i].first==1&&p[i+1].first==1)||(p[i].first==2&&p[i+1].first==2))
{
if((p[i+1].second-p[i].second)%2==0) jud=1;
}
if((p[i].first==1&&p[i+1].first==2)||(p[i].first==2&&p[i+1].first==1))
{
if((p[i+1].second-p[i].second)%2!=0) jud=1;
}
// cout<<p[i].second<<" "<<p[i+1].second<<'\n';
// cout<<p[i].first<<" "<<p[i+1].first<<'\n';
}
if(jud==0) cout<<"YES"<<'\n';
else cout<<"NO"<<'\n';
}
}
D. Lucky Chains
能看到这里的都是高手了,我会简化语言
----------------------------------------题解-------------------------------------
这题可以要吧k=1正无穷最后得到第一个是的gcd(a,b)不等于1的k的暴力枚举的思路转化成一个更巧妙的思路,首先我考虑了用质数筛把所有质数筛出来,k从1正无穷变成了k只用质数一个一个枚举,很不幸也t了,于是我又开始想我们要的是gcd(a+k,b+k),我们这里可以把他转化成gcd(a+k,abs(b-a))我们把b-a看作一个常数q,我们的目标就是找到k的最小值是 gcd(a+k,q)=1...要满足这个条件,我们需要让a+k成为q的质因数的一个倍数(数论知识)例如q=49 质因数为7,倍数为14 21与49的gcd都为1.我们要枚举q的每一个质因子,q然后取一个b-a到这个质因子倍数的最小值我们先办所有我们设质因子为w,我们先把所有w的倍数从q中取出用q不断/w(直到q不能被她的质因子w整除), 然后我们看x要加到这个质因子w的倍数,需要几步
用w-x%w来表示需要x+k的k是多少,然后维护一个最小值即可
点击查看代码
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+5;
const int M=1e6+5;
typedef int ll;
ll primes[N];
#define INF 0x3f3f3f3f
bool st[M];
//typedef long long ll;
ll cnt=0;
void get_primes(int n) // 线性筛质数
{
for (int i = 2; i < n; i ++ )
{
if (!st[i]) primes[cnt++] = i;
for (int j = 0; primes[j] <= n / i&&j<=cnt; j ++ )
{
st[primes[j] * i] = true;
if (i % primes[j] == 0) break;
}
}
}
int main()
{ ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
ll t;
cin>>t;
// cnt++;
// primes[0]=1;
get_primes(M);
while(t--)
{
ll a,b;
cin>>a>>b;
if(__gcd(a,b)!=1) cout<<0<<'\n';
// else if(a%2==0&&b%2==0) cout<<0<<'\n';
// else if(a%2!=0&&b%2!=0) cout<<1<<'\n';
// else if(abs(a-b)==1) cout<<-1<<'\n';
else
{ ll res=abs(b-a);
ll pos=0,ans=INF;
while(primes[pos]<=sqrt(res))
{
if(res%primes[pos]!=0)
{
pos++;
continue;
}
while(res%primes[pos]==0) res=res/primes[pos];
ans=min(ans,primes[pos]- a%primes[pos]);
pos++;
}
if(res>1)ans=min(ans,res-a%res);
cout << (ans == INF ? -1 : ans) << '\n';
}
}
}
//20079 10088
KEEP HARD TO THE END