Wunschの小窝
首页项目归档照片墙音乐灵境说说杂谈友链关于
封面

CF 1109

写作时间:2026-07-16 10:22:09

A

找最长的线段然后向上取整即可。

ACCode:AC Code:ACCode:

#include<bits/stdc++.h>
#define f(i,a,b) for(int i=a;i<=b;i++)
using ll = long long;
using db = double;
ll rd(){ll x=0,w=1;char c=getchar();while(c<'0'||c>'9'){if(c=='-'){w=-1;}c=getchar();}while('0'<=c&&c<='9'){x=x*10+(c-'0');c=getchar();}return x*w;}
using namespace std;

const int MX=500100;
const int mod=998244353;
mt19937 mrd(time(0));

namespace Wunsch{

    ll n,k,m,cnt,ans;
    string s;
    ll a[MX];

    void work(){
        n=rd();
        cin>>s;
        ll mx=0;
        ll len=0;
        f(i,0,n-1){
            if(s[i]=='#')len++;
            else{
                mx=max(mx,len);
                len=0;
            }
        }
        mx=max(mx,len);
        cout<<((mx+1)>>1)<<endl;

        return ;
    }

    bool main(){
        int T=rd();
        while(T--)work();
        return 1;
    }
}

bool amiya=Wunsch::main();

int main(){;}

B

因为只能向后转移,只需要从前往后扫一遍,看看能否构造成以1开始以n-1结束的长度为n-1的数列,并让最后一位数大于等于n,如果可以则有解,反之无解。

ACCode:AC Code:ACCode:

#include<bits/stdc++.h>
#define f(i,a,b) for(int i=a;i<=b;i++)
using ll = long long;
using db = double;
ll rd(){ll x=0,w=1;char c=getchar();while(c<'0'||c>'9'){if(c=='-'){w=-1;}c=getchar();}while('0'<=c&&c<='9'){x=x*10+(c-'0');c=getchar();}return x*w;}
using namespace std;

const int MX=500100;
const int mod=998244353;
mt19937 mrd(time(0));

namespace Wunsch{

    ll n,k,m,cnt,ans;
    string s;
    ll a[MX];

    void work(){
        n=rd();
        ll tmp=0;
        f(i,1,n){
            a[i]=rd();
        }
        f(i,1,n){
            tmp+=a[i]-i;
            if(tmp<0){
                puts("NO");
                return ;
            }
        }
        puts("YES");

        return ;
    }

    bool main(){
        int T=rd();
        while(T--)work();
        return 1;
    }
}

bool amiya=Wunsch::main();

int main(){;}

C

每个点u都向u+x,u-x,u+y,u-y位置连边,我们发现在同一个连通块内的点都可以随意交换,所以只需要用宽搜给下标找到所有的连通块,如果位置上对应的值不在下标所在的连通块中就不可能换到正确的位置(因为是排列,正确的位置一定是值和下标相等的位置)。

ACCode:AC Code:ACCode:

#include<bits/stdc++.h>
#define f(i,a,b) for(int i=a;i<=b;i++)
using ll = long long;
using db = double;
ll rd(){ll x=0,w=1;char c=getchar();while(c<'0'||c>'9'){if(c=='-'){w=-1;}c=getchar();}while('0'<=c&&c<='9'){x=x*10+(c-'0');c=getchar();}return x*w;}
using namespace std;

const int MX=500100;
const int mod=998244353;
mt19937 mrd(time(0));

namespace Wunsch{

    ll n,k,m,cnt,ans;
    string s;
    ll a[MX];
    ll b[MX];
    queue<ll>q;

    void work(){
        n=rd();ll x=rd();ll y=rd();
        f(i,1,n){
            a[i]=rd();
            b[i]=0;
        }
        cnt=1;
        f(i,1,n){
            if(b[i])continue;
            q.push(i);
            b[i]=cnt;
            while(!q.empty()){
                ll u=q.front();q.pop();
                if(u+x>=1&&u+x<=n&&(!b[u+x])){b[u+x]=cnt;q.push(u+x);}
                if(u-x>=1&&u-x<=n&&(!b[u-x])){b[u-x]=cnt;q.push(u-x);}
                if(u+y>=1&&u+y<=n&&(!b[u+y])){b[u+y]=cnt;q.push(u+y);}
                if(u-y>=1&&u-y<=n&&(!b[u-y])){b[u-y]=cnt;q.push(u-y);}
            }
            cnt++;
        }
        bool ok=1;
        f(i,1,n){
            if(b[i]!=b[a[i]]){
                ok=0;
                break;
            }
        }
        ok?puts("YES"):puts("NO");

        return ;
    }

    bool main(){
        int T=rd();
        while(T--)work();
        return 1;
    }
}

bool amiya=Wunsch::main();

int main(){;}

我猜有纯数学做法就去看了一眼题解,下面是笔记。

令g=gcd(x,y)g=gcd(x,y)g=gcd(x,y),显然我们每一步步长一定是g的倍数,所以在模ggg意义下余数始终相等。下面我们要证明余数相等的地方我们一定能到达。由裴蜀定理可得存在aaa和bbb使得ax + by = g成立,即对于任意的g的倍数都一定有解。到这一步我们就会发现,如果忽略数组边界的话一定存在方案使得同一个余数类是联通的。而题目保证了x+y≤nx + y \le nx+y≤n,此时,假设我们在位置iii:

  • 想向左走 xxx(即 i−xi-xi−x),但发现越界了(i−x<1)(i - x < 1)(i−x<1),说明 (i≤x)(i \le x)(i≤x)。此时因为 (x+y≤n)(x + y \le n)(x+y≤n),一定有:i+y≤x+y≤ni + y \le x + y \le ni+y≤x+y≤n,所以向右走 yyy 是安全的。
  • 反过来,如果我们想向右走xxx,但发现越界了(i+x>n)(i + x > n)(i+x>n),说明 (i>n−x)(i > n - x)(i>n−x)。因为 (n−x≥y)(n - x \ge y)(n−x≥y),所以(i−y≥1)(i - y \ge 1)(i−y≥1),向左走yyy是安全的。

‍所以,我们就得到了能排序的充要条件,即∀i,p_i≡i(modg)\forall i,\quad p\_i \equiv i \pmod{g}∀i,p_i≡i(modg)。所以只需要判断每个位置的值与下标是否在模ggg的一个同余类中即可。
‍

avatar

Wunsch

蠕动的区

RECOMMENDED

基础乐理学习笔记(持续更新中)

2026-05-01 21:25:45

Edu 190

2026-05-19 11:26:30

KMP

2026-05-19 21:20:43

Table of Contents