11.25 noip 模拟赛
T1 都不会 QwQ
T1
看出是找最长的等差数列
然后设 \(f_{i,j}\) 表示首项是 \(i\),公差是 \(j\)
写的是 \(O(nm)\) 的
然鹅只有 \(25\) 分,不知道为什么 WA 了
赛后听 lihe_qwq 说正解是枚举 \(k\),找出现最多的 \(b\)(\(kx+b\))
然后复杂度是 \(O(\lfloor \frac{m}{n} \rfloor n)\)
因为 \(k\) 一定是整数
注意判上下界,赛时很多人挂分了
点击查看代码
#include<bits/stdc++.h>
#define int long long
#define ll long long
#define fd(i,a,b) for(int i=(a);i<=(b);i=-~i)
#define bd(i,a,b) for(int i=(a);i>=(b);i=~-i)
#define endl '\n'
using namespace std;
inline int read()
{
int x=0,f=1;char c=getchar();
while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
return x*f;
}
const int N=1e6+509,M=1e6+509,mod=998244353;
int n,m,a[N],ans;
unordered_map<int,int> f;
inline void init()
{
n=read(),m=read();
fd(i,1,n) a[i]=read();
ans=0;
}
void solve(int k)
{
f.clear();
fd(i,1,n)
{
int b=a[i]-k*(i-1);
if(b>0&&k*(n-1)+b<=m)
++f[b],ans=max(ans,f[b]);
}
}
inline void Main()
{
init();
fd(i,0,m/(n-1)) solve(i);
printf("%lld\n",n-ans);
}
signed main()
{
freopen("climb.in","r",stdin);
freopen("climb.out","w",stdout);
int T=read();
while(T--) Main();
return 0;
}
T2
码的 \(O(n^3)\) 的 DP
正解是发现如果交换,那么只有一列的 dp 值会改变
然后就变成 \(O(n^2)\) 了
T3
码的(理论上) \(O(n^3 \log n)\) 的 DP
最劣估计是 \(O(n^4)\),然鹅跑的飞快 (这就叫手法)
然后正解是把平方拆开发现是一个凸壳,然后维护即可
T4
码的 \(O(k \log n \log k)\) 线段树,但是因为数组开小 RE 了
喜提爆蛋
赛后改完交上去,居然有 \(35\)?
正解是分块+线段树,听起来很麻烦
总结
- 一道题如果枚举这个不行可以换另一个枚举,就比如今天的 \(kx+b\),枚举 \(b\) 是 \(O(nm)\),而枚举 \(k\) 是 \(O(\lfloor \frac{m}{n} \rfloor n)\)
- 注意数据范围,数组要开够
本文来自博客园,作者:whrwlx,转载请注明原文链接:https://www.cnblogs.com/whrwlx/p/18567669