2024ICPC西安邀请赛补题

原题

J 找规律

一开始思路错了,光看给的图以为x取整数点,y在整数之间就算超过一半了,忽略了另一个交正方形的点,反例如a=1,b=999

所以x看的是0.5处的点,可以把坐标轴*2避免使用double

cpp 复制代码
void solve(){
  int na,nb;cin>>na>>nb;
  int a=max(na,nb),b=min(na,nb);
  int sm=0;
  for(int i=1;i<=2*a;i+=2){
    int hd=4*b*a-2*b*i;
    int top=hd/(2*a);
    // cout<<top<<' ';
    sm+=(top+1)/2;
  }
  cout<<sm<<endl;
}

M 题意理解

只要被按下,就会触发后面一连串的操作

如果这个按下是被触发的,也会触发对应的一连串

所以按下1后触发的小连招包含x,结束后再主动按x,又会和之前的连招抵消。所以只有1是开的

D 枚举 调和奇数 正难则反 等差数列

等差数列需要确定首相 a 1 a_1 a1和公差 k k k,枚举然后遍历找答案必然超时

遍历找要改的数很浪费,正难则反,确定不用改的数。最小花多少就等于最大省多少。

枚举每个位置为不变,枚举公差k,从 a i ≤ 10 6 a_i\leq 10^6 ai≤106, k ≤ a i i − 1 ≤ 10 6 i − 1 k\leq \frac{a_i}{i-1}\leq \frac{10^6}{i-1} k≤i−1ai≤i−1106,由调和级数k总共最多枚举 10 6 l o g n ≈ 2 e 7 10^6logn\approx 2e7 106logn≈2e7

cpp 复制代码
void solve(){
  int n;cin>>n;
  vector<int>a(n+1),b(n+1);
  forr(i,1,n)cin>>a[i];
  int bsm=0;
  forr(i,1,n)cin>>b[i],bsm+=b[i];
  map<pii,int>match;
  forr(i,1,n){
    forr(k,0,(1e6/i)){
      int a1=a[i]-(i-1)*k;
      if(a1>=0){
        match[{a1,k}]+=b[i];
      }
    }
  }
  int mx=0;
  for(auto [k,v]:match){
    mx=max(mx,v);
  }
  cout<<bsm-mx<<endl;
}

F 博弈

看到样例可以猜一手跟奇偶性有关

发现每位最后一个操作的必能把这一位变成自己想要的数(拿到这一位)

cpp 复制代码
void solve(){
   int k,z;
   cin>>k>>z;
   vector<int>b(k+1),ans(k+1,0);
   vector<int>cnt1;// 记录b=1的地方 AB两人轮流取
   int c=0,c1=0;// c是b>=2的b位奇数个数 c1是b=1的个数
   forr(i,0,k-1){
      cin>>b[i];
      if(b[i]==1){
         cnt1.push_back(i);
         c1++;
      }else if(b[i]==0)ans[i]=0;
      else if(b[i]&1){
         c++;
      }
   }
   /*
      c1:
      - 奇数:取完b=1之后B先手
      - 偶数:之后A先手
      z:
      - 奇:改变先后手
      - 偶:不变
      c:
      - 偶:后手一直演先手,能保证奇数个每个位置都是后手最后拿捏,偶数个部分先手先拿,后手最后拿
            后手都能拿到
      - 奇:先手比后手多一个,能取到最后拿捏的位置;偶数个部分后手先拿
            先手都能拿到
   */
   sort(cnt1.begin(),cnt1.end(),greater<int>());
   forr(i,0,c1-1){
      if(i%2==0)ans[cnt1[i]]=1;// b=1 AB一轮轮争抢
   }
   
   if((c1+c+z)%2){// 三者之和为奇 A最后一个操作 所有b>=2的都能拿到
      forr(i,0,k-1)if(b[i]>=2)ans[i]=1;
   }
   reforr(i,0,k-1)cout<<ans[i];cout<<endl;
}  

L 状压 哈希

暴力规模能达到1e10,超时

因为s长度只有5,可以状压枚举每个位置是否匹配,然后记录每个状态的字符串情况,告诉的和询问的进行匹配,找最大相似度的最小编号

但是用map记录字符串会TLE(退化到了O(n)),使用字符串哈希记录数值

cpp 复制代码
// unordered_map<string,int>rec; TLE 
vector<int>rec(N,inf);// int最大能开536698431
// vector<string>c_vec[25][6];
// int similar(string a,string b){
//    int res=0;
//    forr(i,0,min(a.size(),b.size())-1){
//       if(a[i]!=b[i])break;
//       else res++;
//    }
//    return res;
// }

void solve(){
   int q;cin>>q;
   /* 暴力
      forr(i,1,q){
         int op;cin>>op;
         if(op==1){
            string s;int x;
            cin>>s>>x;
            rec[s]=x;
         }else {
            string s;
            cin>>s;
            int mx=0;string aim;
            for(auto [ss,v]:rec){// 1e5*1e5超时
               int now=similar(ss,s);
               if(now>mx)aim=ss,mx=now;
            }
         }
      }
   */
   
   forr(i,1,q){
      int op;cin>>op;
      if(op==1){
         /*
         利用|s|=5 枚举可能的匹配情况 量化匹配度 状压
         */
         string s;int x;
         cin>>s>>x;
         /*
            forr(i,0,31){
               string now;// 用字符串匹配会TLE 所以使用vector存hash值
               forr(j,0,s.size()-1){
                  // 1:匹配 0:不匹配
                  if((i>>j)&1){
                     now+=s[j];
                  }else now+='#';
               }
               if(!rec[now]||rec[now]>x)rec[now]=x;// 记录固定匹配度 最小编号
            }
         */
         forr(i,0,31){
            int val=0,p=1;
            forr(j,0,s.size()-1){
               // 1:匹配 0:不匹配
               int now=((i>>j)&1)*(s[j]-'a'+1);// a~z 1~26
               val+=now*p;
               p*=27;
            }
            rec[val]=min(rec[val],x);
         }
         
      }else {
         string s;
         cin>>s;
         // int sim_mx=0,ans=1;
         int sim_mx=-1,ans=1;// sim_mx可能最后最大为0 
         /*
            forr(i,0,31){
               string now;
               int sim=0;
               forr(j,0,s.size()-1){
                  // 1:匹配 0:不匹配
                  if((i>>j)&1){
                     now+=s[j];
                     sim++;
                  }else now+='#';
               }
               if(sim>sim_mx&&rec.count(now))ans=rec[now];
            }
         */
         forr(i,0,31){
            int sim=0,val=0,p=1;
            forr(j,0,s.size()-1){
               int now=((i>>j)&1)*(s[j]-'a'+1);
               val+=now*p;
               p*=27;
               sim+=((i>>j)&1);
            }
            if(rec[val]!=inf){
               if(sim>sim_mx)ans=rec[val],sim_mx=sim;
               else if(sim==sim_mx)ans=min(ans,rec[val]);// 找同匹配数下更小的
            }
         }
         cout<<ans<<endl;
      }
   }
}  
相关推荐
浅念-8 小时前
递归解题指南:LeetCode经典题全解析
数据结构·算法·leetcode·职场和发展·排序算法·深度优先·递归
Kiling_07048 小时前
Java集合进阶:Set与Collections详解
算法·哈希算法
智者知已应修善业8 小时前
【51单片机89C51及74LS273、74LS244组成】2022-5-28
c++·经验分享·笔记·算法·51单片机
洛水水9 小时前
【力扣100题】33.验证二叉搜索树
算法·leetcode·职场和发展
SimpleLearingAI9 小时前
聚类算法详解
算法·数据挖掘·聚类
刀法如飞10 小时前
Go 字符串查找的 20 种实现方式,用不同思路解决问题
算法·面试·程序员
Byron Loong11 小时前
【c++】为什么有了dll和.h,还需要包含lib
java·开发语言·c++
Dlrb121111 小时前
C语言-指针数组与数组指针
c语言·数据结构·算法·指针·数组指针·指针数组·二级指针
WL_Aurora11 小时前
Python 算法基础篇之集合
python·算法
坚果派·白晓明11 小时前
【鸿蒙PC三方库移植适配框架解读系列】第一篇:Lycium C/C++ 三方库适配 — 概述与环境配置
c语言·开发语言·c++·harmonyos·开源鸿蒙·三方库·c/c++三方库