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;
      }
   }
}  
相关推荐
ZenosDoron1 小时前
keil软件修改字体,Asm editor,和C/C++ editor的区别
c语言·开发语言·c++
山栀shanzhi2 小时前
C/C++之:构造函数为什么不能设置为虚函数?
开发语言·c++·面试
谭欣辰2 小时前
C++ 版Dijkstra 算法详解
c++·算法·图论
yuan199972 小时前
C&CG(列与约束生成)算法,来解决“风光随机性”下的微网鲁棒配置问题
c语言·开发语言·算法
wayz112 小时前
Day 11 编程实战:XGBoost金融预测与调参
算法·机器学习·金融·集成学习·boosting
念越2 小时前
算法每日一题 Day07|双指针求解和为S的两个数
算法·力扣
qeen872 小时前
【算法笔记】双指针及其经典例题解析
c++·笔记·算法·双指针
黎阳之光2 小时前
黎阳之光:以视频孪生+全域感知,助力低空经济破局突围
大数据·人工智能·算法·安全·数字孪生
CM莫问3 小时前
详解机器学习中的马尔可夫链
人工智能·算法·机器学习·概率论·马尔可夫·马尔科夫