Level 0 牛牛与棋盘

对标cf难度:700
知识点:模拟
签到题。按题意直接打印即可。

#include<bits/stdc++.h>
using namespace std;
#define ll long long

int main(){
    ll n,i,j,k,t,_=1;
   // cin>>_;
    while(_--){
        cin>>n;
        for(i=0;i<n;i++){
            for(j=0;j<n;j++){
                if((i+j)%2==0)cout<<0;
                else cout<<1;
            }
            cout<<endl;
        }
    }

}

level 2 牛牛的“质因数”

对标cf难度:1600
知识点:dfs/dp,数论
我们可以根据x以及x的最小素因子k,推出的值(p≤k):等价于在的前面添加一个p。这个用dfs搜索即可得出答案(需要先筛出4e6以内的素数)

#include<bits/stdc++.h>
using namespace std;
#define ll long long

#define N 4000600
int mod = 1e9+7;
int num[N], prim[5000060];
int pn = 0;
void table(){
    memset(num, -1, sizeof(num));
    for(int i = 2;i < N;i++){
        if(num[i]) prim[pn++] = i;
        for(int j = 0;j < pn && 1LL*i*prim[j] < N;j++){
            num[i*prim[j]] = 0;
            if(i % prim[j] == 0) break;
        }
    }
}

ll power(ll a,ll b){
    ll res=1;
    while(b){
        if(b&1)res=res*a%mod;
        b>>=1;
        a=a*a%mod;
    }
    return res;
}
ll inv(ll x){
    return power(x,mod-2);
}
int a[100010][2];
ll res=0,n;
ll gao(ll x){
    int cnt=0;
    while(x)x/=10,cnt++;
    return cnt;
}
void dfs(ll x,ll val,ll cnt,ll p){  //当前的值 当前的贡献 当前的位数 当前的最小素因子位置
    res=(res+val)%mod;
    for(int i=0;i<=p;i++){
        if(x*prim[i]<=n){
            dfs(x*prim[i],(val+power(10,cnt)*prim[i])%mod,cnt+gao(prim[i]),i);
        }
        else break;
    }
}
int main(){
    table();
    ll i,j,k,m,t,_=1;
   // cin>>_;
    while(_--){
        cin>>n;
        for(i=0;prim[i]<=n;i++){
            dfs(prim[i],prim[i],gao(prim[i]),i);
        }
        cout<<res;
    }

}

level 2 牛牛想要成为hacker

对标cf难度:1500
知识点:构造
前面用斐波那契数列填充,后面全部用1即可。

#include<bits/stdc++.h>
using namespace std;
#define ll long long

#define N 1000600
int mod = 1e9+7;
int num[N], prim[500060];
int pn = 0;
ll res=0,n;

ll a[100010];
int main(){
    a[0]=2;
    a[1]=3;
    ll i,j,k,m,t,_=1;
    for(i=2;i<=40;i++)a[i]=a[i-1]+a[i-2];
 //   cout<<a[40]<<endl;
   // cin>>_;
    while(_--){

        cin>>n;
        for(i=0;i<n;i++){
            if(i<40)cout<<a[i]<<" ";
            else {
                cout<<1<<" ";
               // cout<<a[i]<<" ";
            }
        }
    }

}

level 3 牛牛与交换排序

对标cf难度:1700
知识点:数据结构(双端队列)
这道题使用双端队列(deque)可以达到O(1)进行模拟翻转操作。
具体的方式是:正常情况下队列头进尾出,翻转后尾进头出,用一个变量记录是否翻转的状态即可。
由于k是固定的,并且翻转的区间单调递增,所以可以一次遍历解决本题。

#include<bits/stdc++.h>
using namespace std;
#define ll long long

ll res=0,n;

ll a[100010],b[100010];
int main(){

    ll i,j,k,m,t,_=1;

   // cin>>_;
    while(_--){

        cin>>n;
        int m1=0;
        for(i=1;i<=n;i++){
            cin>>a[i];
        }
        for(i=1;i<=n;i++){
            if(a[i]!=i)break;
        }
        if(i==n+1){
            cout<<"yes\n1";
        }
        else{
            j=i;
            for(i=1;i<=n;i++)if(a[i]==j)break;
            int p=i,out=p-j+1;
            deque<int>q;
            for(i=j;i<p;i++)q.push_back(a[i]);
            int jud=0,temp=j,tt=1;
         //   cout<<p<<endl;
            for(i=p;i<=n;i++){
                if(tt){q.push_back(a[i]);}
                else q.push_front(a[i]);
                if(q.back()==temp){
                    q.pop_back();
                    tt=0;
                }
                else if(q.front()==temp){
                    q.pop_front();
                    tt=1;
                }
                else {jud=1;break;}
                temp++;
            }
            if(!jud){
                j=0;
                for(deque<int>::iterator it=q.begin();it!=q.end();it++){
                    b[j++]=(*it);
                //    cout<<(*it)<<endl;
                }
               // cout<<temp<<" "<<p<<endl;
                if(b[0]==temp){
                    for(i=0;i<j;i++){
                        if(b[i]!=temp+i)jud=1;
                    }
                }
                else{
                    for(i=0;i<j;i++){
                        if(b[i]!=n-i)jud=1;
                    }
                }
            }
            if(jud)cout<<"no";
          else   cout<<"yes"<<endl<<out;
        }
     //   cout<<a[i-1];
    }

}
/*
5
3 4 5 1 2
*/

level 3 牛牛与字符串border

对标cf难度:1800
知识点:字符串
分类讨论。
如果,那么k、2k、...都要满足要求,在纸上画一下容易得出重复段长度为gcd(k,n)。
如果,可以发现重复段长度为即可。
用桶记录一下每个对应位置的次数,求出最大值。

#include<bits/stdc++.h>
using namespace std;
int main(){
    int t;
    cin>>t;
    while(t--){
        int n,m,i,j;
        string s;
        cin>>n>>m;
        cin>>s;
        string out="";
        int g=__gcd(n,m);
        if(n<m*2&&n!=m)g=n-m;
        for(i=0;i<g;i++){
            int tong[26]={0};
            for(j=i;j<n;j+=g){
                tong[s[j]-'a']++;
            }
            int ma=0,mi=0;
            for(j=0;j<26;j++){
                if(tong[j]>ma)ma=tong[j],mi=j;
            }
            out+='a'+mi;
        }
        for(i=0;i<n/g;i++)cout<<out;
        for(i=0;i<n%g;i++)cout<<out[i];
        cout<<endl;
    }
}

level 3 牛牛与整除分块

对标cf难度:1700
知识点:数论
将n/k分为两部分:若,那么每个n/k都是不同的。否则每个n/k都是相同或连续的。
但需要注意特判一种特殊情况:若,那么,这时n/x向下取整是x-1,和n/k=x+1相差为2,需要特判。
ps:这道题卡输入卡吐了。。不关同步cin会超时,关同步带endl会超时。
目前经过实验得出的结论是:关闭同步,并且不使用endl而是用'\n'是最快的,其次是scanf。不关同步或者使用endl都特别慢,遇到1e6级别的输入输出直接爆炸。。

#include<bits/stdc++.h>
using namespace std;
#define ll long long

#define N 1000600
int mod = 1e9+7;
int num[N], prim[500060];
int pn = 0;

ll res=0,n;

ll a[100010];
int main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    a[0]=1;
    a[1]=1;
    ll i,j,k,m,t,_=1;

    scanf("%lld",&_);
   // cin>>_;
    while(_--){

        scanf("%lld%lld",&n,&k);
        if(k*k<=n)printf("%lld\n",k);
        else {
            ll cnt=sqrt(n);
            cnt+=5;
            while(cnt*cnt>n)cnt--;
            int jud=0;
            if(cnt*(cnt+2)==n)jud++;
            printf("%lld\n",cnt+(n/cnt-n/k)-jud);
        }
     //   cout<<a[i-1];
    }

}

level 4 牛牛与比赛颁奖

对标cf难度:2100
知识点:离散化、差分前缀和
这道题题意很明显,思路也很明显,按照题意模拟就行。注意数据范围到了1e9,这样离散化一下就变成1e5的数量级了。

#include<bits/stdc++.h>
using namespace std;
#define ll long long

#define N 1000600
int mod = 1e9+7;
int num[N], prim[500060];
int pn = 0;

ll res=0,n;

ll a[100010][2],lsh[300030],sum[300030],tong[100010];
map<int,int>mp;
int main(){

    ll i,j,k,m,t,_=1;

   // cin>>_;
    while(_--){

        cin>>n>>m;
        int c1=n/10+(n%10!=0),c2=n/4+(n%4!=0),c3=n/2+(n%2!=0);
        c1=max(c1,1);
        c1=max(c1,1);
        c1=max(c1,1);
        set<int>s;
        for(i=0;i<m;i++){
            int l,r;
            cin>>l>>r;
            a[i][0]=l;
            a[i][1]=r;
            s.insert(r+1);
            s.insert(l);
            s.insert(r);
        }
        j=1;
        for(set<int>::iterator it=s.begin();it!=s.end();it++){
            lsh[j]=(*it);
            mp[(*it)]=j++;
        }
        for(i=0;i<m;i++){
            int l=a[i][0],r=a[i][1];
            sum[mp[l]]++,sum[mp[r+1]]--;
        }

        for(i=1;i<300000;i++){
            sum[i]+=sum[i-1];
        }
        for(i=1;i<300000;i++){
            if(sum[i]){
                tong[sum[i]]+=lsh[i+1]-lsh[i];
            }
        }
     //   for(i=1;i<=m+1;i++)cout<<tong[i]<<endl;
      //  cout<<endl;
        int o1=0,o2=0,o3=0,temp=0;
   //     cout<<c1<<" "<<c2<<" "<<c3<<endl;
        int ou1=0,ou2=0,ou3=0;
        for(i=m;i>0;i--){
            temp+=tong[i];
          //  cout<<i<<" "<<temp<<endl;
            if(temp>=c1&&!o1)o1=i;
            if(temp>=c2&&!o2)o2=i;
            if(temp>=c3&&!o3)o3=i;
        }
        for(i=m;i>0;i--){
            if(i>=o1)ou1+=tong[i];
            else if(i>=o2)ou2+=tong[i];
            else if(i>=o3)ou3+=tong[i];
        }
        cout<<ou1<<" "<<ou2<<" "<<ou3<<endl;
       // cout<<tong[o3]<<" "<<tong[o2]<<" "<<tong[o1]<<endl;

    }

}

level 4 牛牛与跷跷板

对标cf难度:2000
知识点:最短路、双指针
看到这个题应该第一时间想到bfs求最短路,但怎么建图是个难点。
我的方法是:首先开1e5个vector。第i个vector存纵坐标为i的跷跷板(用结构体,存l、r以及跷跷板编号)。
然后对每个vector进行排序,这样在搞第i个vector的时候,可以用另外一个指针扫下一个vector,这样就能达成O(n)建图了。

#include<bits/stdc++.h>
using namespace std;
#define ll long long

#define N 1000600
int mod = 1e9+7;
int num[N], prim[500060];
int pn = 0;

ll res=0,n;

struct line{
    int l,r,i;
};
vector<line>a[100010];
vector<int>g[100010];
int dep[100010],visited[100010];
bool cmp(line a,line b){
    return a.l<b.l;
}
map<int,int>mp;
void out(){
    int i,j;
    for(i=0;i<4;i++){
        cout<<i<<":"<<endl;
        for(j=0;j<g[i].size();j++){
            cout<<g[i][j]<<" ";
        }
        cout<<endl;
    }
}
int main(){

    ll i,j,k,m,t,_=1;
   // table();
 //   cout<<a[40]<<endl;
   // cin>>_;
    while(_--){
        cin>>n;
        for(i=1;i<=n;i++){
            int y;
            line temp;
            cin>>y;
            cin>>temp.l>>temp.r;
            temp.i=i;
            a[y].push_back(temp);
        }

        for(i=0;i<=1e5;i++)sort(a[i].begin(),a[i].end(),cmp);
        for(i=0;i<=1e5;i++){

            k=0;
            for(j=0;j<a[i].size();j++){
                if(j<a[i].size()-1&&a[i][j].r==a[i][j+1].l){
                    int u=a[i][j].i,v=a[i][j+1].i;
                    g[u].push_back(v);
                    g[v].push_back(u);
                }
                if(i==1){
               //     cout<<a[i][0].l<<" "<<a[i+1][0].r<<endl;
                }
                while(k<a[i+1].size()&&a[i+1][k].r<=a[i][j].l)k++;
                while(k<a[i+1].size()&&a[i+1][k].l<a[i][j].r){
                    int u=a[i][j].i,v=a[i+1][k].i;

                    g[u].push_back(v);
                    g[v].push_back(u);
                    k++;
                }
                k--;
            }
        }
       // out();


        queue<int>q;
        q.push(1);
        visited[i]=1;
        while(!q.empty()){
            int temp=q.front();
            for(i=0;i<g[temp].size();i++){
                if(!visited[g[temp][i]]){
                    visited[g[temp][i]]=1;
                    dep[g[temp][i]]=dep[temp]+1;
                    q.push(g[temp][i]);
                }
            }
            q.pop();
        }
        cout<<dep[n];


    }

}
/*
4
1 2 5
0 0 4
1 0 1
2 0 3

*/

剩下的两道题一个数据结构,一个图论,都是我比较弱的部分(我有个数据结构和图论很强的队友,所以先不补了ww这两个题让队友补)
这场比赛的题目质量非常高,%%%%%%%智乃姐姐