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

posted @ 2024-07-18 21:10  marisa3  阅读(27)  评论(0编辑  收藏  举报