codeforces 779 div2 A~D

A Marin and Photoshoot

字符串中两个零之间至少间隔两个一,使用for循环判断一遍即可

int main()
{
    string s;int t;
    cin>>t;
    while(t--)
    {
        int n; string s;
        cin>>n>>s;
        int l=-3; int ans=0;
        for(int i=0;i<n;i++)
        {
            if(s[i]=='0')
            {
                if(i-l<=2)
                {
                  ans+=3-(i-l);  
                }
                l=i;
            }
        }
      cout<<ans<<endl;
    }
    return 0;
}

B Marin and Anti-coprime Permutation

给定数组长度为N,数组内的元素是集合(1~N)的所有数,将数组进行排列满足下列条件的排列方式有多少种
g c d ( 1 ∗ a [ 1 ] , 2 ∗ a [ 2 ] . . . i ∗ a [ i ] . . . n ∗ a [ n ] ) > 1 gcd(1*a[1],2*a[2]...i*a[i]...n*a[n])>1 gcd(1a[1],2a[2]...ia[i]...na[n])>1

观察样例发现当数组长度为奇数时,无论怎么排列,最大公约数都是1,当数组长度为偶数时,只需要将偶数放在奇数位上,奇数放在偶数位上,最大公约数便大于1,所以当数组长度为偶数时,计算(n/2)(n2)

using namespace std;
const int N=1e3+10,mod=998244353;
ll a[N];
int main()
{   ll res=1;
    for(int i=1;i<=500;i++)//预处理
    {
      res=i*res%mod;
          a[i*2]=res*res%mod;
      
    }
    int t;
    cin>>t;
    while(t--)
    {
        int n;
        cin>>n;
        cout<<a[n]<<endl;
    }
    return 0;
}

C Shinju and the Lost Permutation

找到数组中1的位置,把1前面的数添到数组后面,从1开始遍历整个数组,在数组的遍历过程中只要一直满足a[i]-a[i-1]<=1,c数组就合法,注意数组里面应有且只有一个1

const int N=2e5+10;
int a[N];
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        int n;
        cin>>n;
        for(int i=1;i<=n;i++)
        {
            cin>>a[i];
        }
        int num=n+1;
          int i=1;
          int f=1;
          while(a[i]!=1)
          {
              a[num++]=a[i];
              i++;
              if(i>n)
              {
                  f=0;
                  break;
              }
          }
          if(!f) //如果没有1
          {
              cout<<"NO"<<endl;
              continue;
          }
          for(int j=i+1;j<num;j++)
          {
               if(a[j]==1)//只能有一个1
               {
                   f=0;
                   break;
               }
               if(a[j]-a[j-1]>1) 
               {
                   f=0;
                   break;
               }
          }
          if(f)
          cout<<"YES"<<endl;
          else 
          cout<<"NO"<<endl;
    }
    return 0;
}

D 388535

a ⊕ b a\oplus b ab=c则 c ⊕ a c\oplus a ca=b所以对于l来说 l ⊕ x l\oplus x lx=a, a ⊕ l a\oplus l al=x,只需遍历数组a,假设x= a [ i ] ⊕ l a[i]\oplus l a[i]l,再有x来异或a数组,找到异或之后的最大值和最小值,因为a数组中的元素个个不同,a数组异或x之后也是个个不同的,只要最大值等于,r最小值等于l,x就是我们要找的答案。使用01字典树来查询最大值和最小值。

#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <cstring>
#include <queue>
#include <stack>
#include <map>
#include <vector>
#include <set>
#include <ctime>
#include <utility>
#include <unordered_map>
#include <random>
#define MM(x, y) memset(x, y, sizeof(x))
#define lowbit(x) ((x) & (-x))
#define ll long long
#define INF 0x3f3f3f3f
#define bug puts("bugbugbug");

//priority_queue<int,vector<int>,greater<int> >c;


using namespace std;
const int N=5e5+10;
int a[N],s[N*20][2],idx=0;

void init()
{
    idx=0;
    s[0][0]=s[0][1]=0;
}
void insert(int x)  //
{
     int p=0;
     for(int i=20;~i;i--)
     {
         int t=x>>i&1;
         if(!s[p][t])
         {s[p][t]=++idx;
          s[idx][0]=s[idx][1]=0;  //因为数据量大,将要用到那个点时,我们再将它恢复到默认值
         }
         p=s[p][t];

     }
}

int query(int x)//查询最大值
{
    int p=0;
    int ans=0;
    for(int i=20;~i;i--)
    {
        int t=x>>i&1;
        if(s[p][!t])
        {
            ans+=1<<i;
            p=s[p][!t];
        }
        else 
        p=s[p][t];
    }
    return ans;
}
int query1(int x)  //查询最小值
{
    int p=0;
    int ans=0;
    for(int i=20;~i;i--)
    {
        int t=x>>i&1;
        if(s[p][t])
        {
            p=s[p][t];
        }
        else 
        {
            ans+=1<<i;
            p=s[p][!t];
        }
    }
    return ans;
}
int main()
{  cin.tie(0);
   int t;
   scanf("%d",&t);
   while(t--)
   {   init();
       int l,r;
       scanf("%d %d",&l,&r);
       idx=0;
       for(int i=l;i<=r;i++)
       {
         scanf("%d",&a[i]);
         insert(a[i]);
       }
       for(int i=l;i<=r;i++)
       {
         int x=query(a[i]^l);
         int y=query1(a[i]^l);   
         if(x==r&&y==l)
         {
            printf("%d\n",(a[i]^l));
            break;
         }  
       }
   }
   return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值