1 条题解

  • 0
    @ 2026-5-6 18:38:41

    其实是数论基础题。

    考虑状态的设计:fi,Pf_{i,P} 表示考虑了前 ii 个元素,要求 j=i+1nbjP\prod\limits_{j=i+1}^n b_j\ge P 的最大答案。由于 PP 必然形如 kx\left\lceil\frac{k}{x}\right\rceil,根据整除分块的理论可能的 PP 个数是 O(k)O(\sqrt{k}) 的——于是状态数变为 O(nk)O(n\sqrt{k}),直接暴力枚举 bib_i 转移时间复杂度为 O(nkmaxai)O(n\sqrt{k}\max a_i),可以获得 2525 分。

    发现对于某一些 bib_iPbi\left\lceil\frac{P}{b_i}\right\rceil 的值是一样的,也就是说可以对于 [1,P][1,P] 内的值再套一层整除分块!这样的时间复杂度是 $O\left(n\left(\sum\limits_{m=1}^{\sqrt{k}}\sqrt{m}+\sqrt{\left\lceil\frac{k}{m}\right\rceil}\right)\right)=O(nk^{\frac{3}{4}})$,证明可以参考 杜教筛 - OI Wiki。于是本题得以解决。

    实现时注意到 $\left\lceil\frac{k}{x}\right\rceil=\left\lfloor\frac{k-1}{x}\right\rfloor+1$,所以可以转换为 k1k-1 的下取整整除分块。这里注意特判 k1x=0\left\lfloor\frac{k-1}{x}\right\rfloor=0 的情况,转移时单独提出来处理。

    放代码:

    #include<bits/stdc++.h>
    using namespace std;
    int main(){
      ios::sync_with_stdio(false);
      cin.tie(0); cout.tie(0);
      int n,k; cin>>n>>k,k--;
      vector<int> a(n),w;
      for(auto &i:a)cin>>i;
      for(int l=1,r;l<=k;l=r+1)
        w.emplace_back(k/l),r=k/(k/l);
      w.emplace_back(0); // 预处理第二维的可能值
      vector<int> p(k+1,-1);
      for(int i=0;i<w.size();i++)
        p[w[i]]=i; // 记一下位置方便转移时快速查找
      vector<double> f(w.size());
      f[0]=k+1;
      for(int x:a){
        vector<double> g(w.size());
        for(int i=0;i<w.size();i++)
          if(f[i]){
            for(int l=1,r;l<=w[i];l=r+1){
              int v=w[i]/l;
              g[p[v]]=max(g[p[v]],f[i]*(x/l)/x),r=w[i]/v;
            } // 整除分块进行转移
            g.back()=max(g.back(),f[i]*(x/(w[i]+1))/x);
            // 特判值为 0
          }
        f=move(g); // 使用滚动数组
      }
      cout<<fixed<<setprecision(11)<<f.back()<<endl;
      return 0;
    }
    
    • 1

    「OOI 2023 Day 1」又一个 n 维巧克力

    信息

    ID
    11049
    时间
    2000ms
    内存
    512MiB
    难度
    10
    标签
    递交数
    1
    已通过
    1
    上传者