NOIP2022模拟赛一 By QY8.16
Preface
今天这场代码量好小啊……
T4原来是经典的除法分块,但我都忘光了,远程求助陈指导才会
A. 「NOIP2022模拟赛一 By QY A」签到题
Pro
- 构造一个长度为的排列,使得其是所有排列中最小的一个(相同则输出任意一种)
- 分别表示的最长上升子序列长度和最长下降子序列长度
Sol
刚开始有点迷,打了个暴力找了下规律就会了
不难证明的最小值就是,考虑以下的构造方法:
n=9
3 2 1 6 5 4 9 8 7
n=11
3 2 1 7 6 5 4 11 10 9 8
普遍地,把序列分为一些大小为的块,块的内部保证连续降序,然后块的总数也是级别的,升序子序列只能存在与不同的块之间
#include<cstdio>
#include<cmath>
#include<algorithm>
#define RI register int
#define CI const int&
using namespace std;
const int N=100005;
int n,a[N],m;
int main()
{
RI i,j,k; scanf("%d",&n); m=(int)sqrt(n); if (m*m<n) ++m;
for (i=n-m+1,k=n;i>=1;i-=m) for (j=0;j<m;++j) a[i+j]=k--;
for (i=1;i<=n%m;++i) a[i]=k--;
for (i=1;i<=n;++i) printf("%d ",a[i]);
return 0;
}
B. 「NOIP2022模拟赛一 By QY B」简单题
Pro
- 在一个圆中随机分布着个点,求存在一条直径使得所有点均在直线一侧的概率
- ,答案对取模
Sol
首先在圆内和在圆周上是等价的,然后考虑先选定一个点为起点
以这个起点为端点,规定一个方向(假定为逆时针)做得一段半圆周,我们强制接下来的点都要落在这个半圆周上
剩下个点都落在上面的概率是,再乘上起点选法就是答案了
#include<cstdio>
#include<cmath>
#include<algorithm>
#define RI register int
#define CI const int&
using namespace std;
const int mod=998244353;
int n;
inline int quick_pow(int x,int p=mod-2,int mul=1)
{
for (;p;p>>=1,x=1LL*x*x%mod) if (p&1) mul=1LL*mul*x%mod; return mul;
}
int main()
{
return scanf("%d",&n),printf("%d",1LL*n*quick_pow(quick_pow(2,n-1))%mod),0;
}
C. 「NOIP2022模拟赛一 By QY C」数列题
Pro
- 有一个长度为的数列,在初始时是整数,后续过程中可以变成实数
- 你可以对一个数进行一次修改,将其值变为,这要花费的代价
- 求让最后的数列变为等差数列的最小代价总和
- ,数据组数T\le 1000$
Sol
考虑等差数列的一般表达形式,,把看做自变量,看做因变量,这其实就是一条直线的方程
而且我们发现原来给出的值可以看做在平面内的点,而代价的定义也和SSE(残差平方和)一模一样
因此我们直接使用线性回归的相关知识,用最小二乘法得到最优的拟合直线,有:
就可以轻松算出答案了,复杂度
#include<cstdio>
#include<cctype>
#include<algorithm>
#define RI register int
#define CI const int&
#define Tp template <typename T>
using namespace std;
const int N=1005;
int t,n,a[N]; double _x,_y,f1,f2,k,b,ans;
class FileInputOutput
{
private:
static const int S=1<<21;
#define tc() (A==B&&(B=(A=Fin)+fread(Fin,1,S,stdin),A==B)?EOF:*A++)
char Fin[S],*A,*B;
public:
Tp inline void read(T& x)
{
x=0; char ch; bool flag=0; while (!isdigit(ch=tc())) if (ch=='-') flag=1;
while (x=(x<<3)+(x<<1)+(ch&15),isdigit(ch=tc())); if (flag) x=-x;
}
#undef tc
}F;
inline double sqr(const double& x) { return x*x; }
int main()
{
//freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout);
for (F.read(t);t;--t)
{
RI i; for (F.read(n),_x=_y=f1=f2=ans=0,i=1;i<=n;++i)
F.read(a[i]),_x+=i,_y+=a[i]; _x/=n; _y/=n;
for (i=1;i<=n;++i) f1+=(i-_x)*(a[i]-_y),f2+=sqr(i-_x);
for (k=f1/f2,b=_y-k*_x,i=1;i<=n;++i) ans+=sqr(a[i]-(k*i+b));
printf("%.15lf\n",ans);
}
return 0;
}
D. 「NOIP2022模拟赛一 By QY D」化学题
Pro
- 有一个数初值为,每秒钟它就会等概率随机变为原来的倍
- 求该数第一次大于的期望时间
Sol
暴力DP人人都会,就是要注意不变的情况,单独提出来后把转移方程移项后即可:
考虑从入手,用整除分块后状态变成了级别,同时在转移的时候也可以再套一个整除分块来把相同的值一起转移
总体复杂度(和杜教筛的复杂度类似,两个除法分块套在一起就是这个复杂度)
#include<cstdio>
#include<iostream>
#include<cmath>
#define RI register int
#define CI const int&
using namespace std;
const int S=100000,mod=998244353;
int n,m,sm,st[S<<1],cnt,inv,id1[S],id2[S],f[S<<1];
inline int quick_pow(int x,int p=mod-2,int mul=1)
{
for (;p;p>>=1,x=1LL*x*x%mod) if (p&1) mul=1LL*mul*x%mod; return mul;
}
inline void inc(int& x,CI y)
{
if ((x+=y)>=mod) x-=mod;
}
#define ID(x) ((x)<=sm?id1[x]:id2[m/(x)])
int main()
{
RI i,l,r; scanf("%d%d",&n,&m); sm=sqrt(m);
for (l=1;l<=m;l=r+1) r=m/(m/l),st[ID(m/l)=++cnt]=m/l;
for (inv=quick_pow(n-1),i=cnt;i;--i)
{
for (l=2;l<=min(n,st[i]);l=r+1)
r=min(n,st[i]/(st[i]/l)),inc(f[i],1LL*(r-l+1)*f[ID(st[i]/l)]%mod);
f[i]=1LL*(f[i]+n)*inv%mod;
}
return printf("%d",f[ID(m)]),0;
}
Postscript
咕噜咕噜咕噜……
辣鸡老年选手AFO在即
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
2019-08-16 Codeforces Round #573 (Div. 1)