洛谷NOIp热身赛题解


A 最大差值

简单树状数组,维护区间和、区间平方和,方差按照给的公式算就行了

#include<bits/stdc++.h>
#define il inline
#define vd void
#define mod 1000000007
typedef long long ll;
namespace IO{
const int maxn=(1<<21)+1;
char ibuf[maxn],*iS,*iT,c;int f;
inline char getc(){
return iS==iT?(iT=(iS=ibuf)+fread(ibuf,1,maxn,stdin),iS==iT?EOF:*iS++):*iS++;
}
inline int gi(){
int x=0;
for(f=1,c=getc();(c<'0'||c>'9');c=getc())f=c=='-'?-1:1;
for(x=0;(c>='0'&&c<='9');c=getc())x=(x<<1)+(x<<3)+(c^48);
return x*f;
}
}
using IO::gi;
int b[100010];
int inv[100010];
int sum[100010<<4],SUM[100010<<4],N;
#define mid ((l+r)>>1)
il vd build(int n){
N=1<<(int)ceil(log(n+2)/log(2));
for(int i=1;i<=n;++i)sum[i+N]=b[i],SUM[i+N]=1ll*b[i]*b[i]%mod;
for(int i=N-1;i;--i)sum[i]=(sum[i<<1]+sum[i<<1|1])%mod,SUM[i]=(SUM[i<<1]+SUM[i<<1|1])%mod;
}
il vd update(int p,int d){
p+=N,sum[p]=d,SUM[p]=1ll*d*d%mod;
for(p>>=1;p;p>>=1)sum[p]=(sum[p<<1]+sum[p<<1|1])%mod,SUM[p]=(SUM[p<<1]+SUM[p<<1|1])%mod;
}
il std::pair<int,int> query(int l,int r){
--l,++r;l+=N,r+=N;
int ret=0,RET=0;
while(l^r^1){
if(~l&1)ret=(sum[l^1]+ret)%mod,RET=(SUM[l^1]+RET)%mod;
if(r&1)ret=(sum[r^1]+ret)%mod,RET=(SUM[r^1]+RET)%mod;
l>>=1;r>>=1;
}
return std::make_pair(ret,RET);
}
int main(){
int n=gi(),m=gi();
inv[1]=1;for(int i=2;i<=n;++i)inv[i]=mod-1ll*(mod/i)*inv[mod%i]%mod;
for(int i=1;i<=n;++i)b[i]=gi();
build(n);
int o,l,r;
while(m--){
o=gi();
if(o==1)l=gi(),r=gi(),update(l,r);
else{
l=gi(),r=gi();
std::pair<int,int>A=query(l,r);
int sa=A.first,SA=A.second;
int pa=1ll*sa*inv[r-l+1]%mod;
printf("%lld\n",1ll*inv[r-l+1]*(1ll*pa*pa%mod*(r-l+1)%mod+SA-1ll*2*sa*pa%mod+mod)%mod);
}
}
return 0;
}

B 攀爬者

C 蜈蚣

简单dp,设f[i][j]为1-j分成i段的最大收益,f[i][j]=max(f[i-1][k]+(A[k+1] xor ... xor A[j]))

#include<bits/stdc++.h>
#define il inline
#define vd void
typedef long long ll;
il int gi(){
int x=0,f=1;
char ch=getchar();
while(!isdigit(ch)){
if(ch=='-')f=-1;
ch=getchar();
}
while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
return x*f;
}
int f[2][1010],W[1010];
il vd chkmx(int&a,int b){if(b>a)a=b;}
int main(){
int n=gi(),m=gi();
register int x=0,i,j,k;
for(i=1;i<=n;++i)W[i]=gi()^W[i-1];
memset(f[x]+1,-127,n<<2);
for(i=1;i<=m;++i){
x^=1;
memset(f[x],-127,i<<2);
for(j=i;j<=n;++j){
f[x][j]=0;
for(k=i-1;k<=j;++k)
chkmx(f[x][j],f[x^1][k-1]+(W[j]^W[k-1]));
}
}
printf("%d\n",f[x][n]);
return 0;
}

D 漂浮的鸭子

同消息传递,略

E 最大差值

F 随机数生成器

70分可以dp,设\(f[i]\)表示\(i\)到\(1\)的期望,那么\(f[1]=0,f[i]=1+\frac{\sum_{j=1}^{i}f[j]}{i}(i>1)\)

\(\frac{i-1}{i}f[i]=1+\frac{\sum_{j=1}^{i-1}f[j]}{i}\)

然后100分可以发现\(f[i]=1+(1/1+1/2+...+1/(i-1))\),后面的调和级数可以直接套公式

#include<bits/stdc++.h>
#define il inline
#define vd void
typedef long long ll;
il int gi(){
int x=0,f=1;
char ch=getchar();
while(!isdigit(ch)){
if(ch=='-')f=-1;
ch=getchar();
}
while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
return x*f;
}
int main(){
int n=gi();if(n==1)return puts("0.00000"),0;
double ans=1;
if(n<=1000000)for(int i=1;i<n;++i)ans+=1.0/i;
else ans=1+log(n-1)+0.5772156649015;
printf("%.5lf\n",ans);
return 0;
}

G 大循环

题面看着很nb,实际上上下的a没有关系,F(q)是个定值,答案就是\(C_{n}^{k}\times F(q)\)

#include<bits/stdc++.h>
#define il inline
#define vd void
#define mod 1000000007
#define int ll
typedef long long ll;
il ll gi(){
ll x=0,f=1;
char ch=getchar();
while(!isdigit(ch)){
if(ch=='-')f=-1;
ch=getchar();
}
while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
return x*f;
}
int p[500010];
il int pow(int x,int y){
int ret=1;
while(y){
if(y&1)ret=1ll*ret*x%mod;
x=1ll*x*x%mod;y>>=1;
}
return ret;
}
signed main(){
ll n=gi(),m=gi(),k=gi(),q=gi()%mod,F=0;
for(int x=1,i=0;i<=m;++i,x=1ll*x*q%mod)F=(F+1ll*x*gi()%mod)%mod;
p[0]=1;for(int i=1;i<=n;++i)p[i]=1ll*p[i-1]*i%mod;
printf("%lld\n",1ll*p[n]*pow(1ll*p[k]*p[n-k]%mod,mod-2)%mod*F%mod);
return 0;
}

H 会议座位

I 生日礼物

选两个数使得lcm=a,单独考虑a的每个质因数\(p^k\),那么这两个数一定有一个会有\(p^k\),另一个可以是\(p^{(0-k)}\),所以\(p^k\)有\(2k+1\)中选法。给a分解质因数,\(ans=\Pi(2k+1)\)

J HKE与他的小朋友

K 宝藏

二维树状数组 区间异或 区间查询异或和

和一维树状数组区间修改区间查询一样,记\(d(x,y)\)为\((x,y,n,n)\)这个子矩形的共同增量,查询\((x_0,y_0)\)只需查询\((1,1,x_0,y_0)\)的异或和。

冷静分析,\(d(x,y)\)在\((1,1,x_0,y_0)\)出现了奇数次才要计算\(d(x,y)\),条件就是\((x_0-x+1)(y_0-y+1)\)为奇数,那么\(x,x_0\)同奇偶,\(y,y_0\)同奇偶,对于每一种\(x,y\)的奇偶情况开一个树状数组即可,一共4个

#include<bits/stdc++.h>
#define il inline
#define vd void
typedef long long ll;
il int gi(){
int x=0,f=1;
char ch=getchar();
while(!isdigit(ch)){
if(ch=='-')f=-1;
ch=getchar();
}
while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
return x*f;
}
int n,m,N;
int t[2][2][1271][1271];
il vd update(int x,int y,int d){
int X=x&1,Y=y&1;x=(x+1)>>1,y=(y+1)>>1;
for(int i=x;i<=N;i+=i&-i)
for(int j=y;j<=N;j+=j&-j)
t[X][Y][i][j]^=d;
}
il int query(int x,int y){
int ret=0,X=x&1,Y=y&1;x=(x+1)>>1,y=(y+1)>>1;
for(int i=x;i;i-=i&-i)
for(int j=y;j;j-=j&-j)
ret^=t[X][Y][i][j];
return ret;
}
int main(){
n=gi(),m=gi();N=(n+1)>>1;
int x0,y0,x1,y1;char ch;
for(int i=1;i<=m;++i){
do ch=getchar();while(ch!='P'&&ch!='Q');
x0=gi(),y0=gi(),x1=gi(),y1=gi();
if(ch=='P'){
int t=gi(),S=0,a,b;
while(t--)a=gi(),b=gi(),S^=(b&1)<<(a-1);
update(x0,y0,S);
update(x0,y1+1,S);
update(x1+1,y0,S);
update(x1+1,y1+1,S);
}else{
int ans=query(x1,y1)^query(x1,y0-1)^query(x0-1,y1)^query(x0-1,y0-1);
for(int i=0;i<30;++i)putchar('1'+((ans>>i)&1));
puts("");
}
}
return 0;
}

L 简单的函数

回顾一下题目意思,对每个\(x\)找到最小的\(t\)满足\(t\not\mid x\),\(f(x)=f(t)+1\)

倒过来考虑,对每个\(t\)会转移到多少个\(x\)。(称为\(t\)的答案)\(x\)如果从\(t\)转移过来,那么\(lcm(1,2,...,t-1)\mid x,lcm(1,2,...,t)\not\mid x\)。

先考虑\(lcm(1,2,...,t-1)|x\),也就是说\(x\)是\(lcm(1,2,...,t-1)\)的倍数。满足这个的\(x\)有\(\lfloor\frac{n}{lcm(1,2,...,t-1)}\rfloor\)个。还要减去\(lcm(1,2,...,t)\mid x\)的情况,也就是所有\(t'>t\)的答案。

注意到\(lcm(1,...,42)\)大约是\(2*10^{17}\),那么可行的\(t\)不会超过\(42\),从\(42\)开始算即可。

#include<bits/stdc++.h>
#define il inline
#define vd void
#define mod 1000000007
#define int ll
typedef long long ll;
il int gi(){
int x=0,f=1;
char ch=getchar();
while(!isdigit(ch)){
if(ch=='-')f=-1;
ch=getchar();
}
while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
return x*f;
}
il ll lcm(ll a,ll b){return a/std::__gcd(a,b)*b;}
ll f[]={0,0,1,2,3,2,4,2,3,2,3,2,3,2,3,2,3,2,4,2,3,2,3,2,3,2,3,2,3,2,4,2,3,2,3,2,3,2,3,2,3,2,4,2};
il int pow(int x,int y){
int ret=1;
while(y){
if(y&1)ret=1ll*ret*x%mod;
x=1ll*x*x%mod;y>>=1;
}
return ret;
}
ll L[50],a[50];
signed main(){
int n=gi();
L[1]=1;for(int i=2;i<=42;++i)L[i]=lcm(i,L[i-1]);
ll ans=1,sum=0;
for(int i=42;i;--i){
a[i]=n/L[i]-sum;
if(L[i]<=2)--a[i];
if(i==1)--a[i];
ans=1ll*ans*pow(f[i+1]+1,a[i])%mod;
sum+=a[i];
}
printf("%lld\n",ans);
return 0;
}

M 数列游戏

先dp一遍,\(f[l][r]\)表示\([l,r]\)这个区间里的数能否被消完,那么\(f[i][i+1]=[gcd(A[i],A[i+1])!=1]\)

\(f[l][r]\)有两种转移

  1. \(f[l+1][r-1] (gcd(A[l],A[r])!=1)\),先消完\([l+1,r-1]\),再消掉\(l,r\)
  2. \(f[l][k],f[k+1][r]\),消掉\([l,k]\)到\([k+1],r\)

这一段是\(O(n^3)\)的(我也不知道为啥能过)

然后就知道了哪些区间能用。剩下的看代码吧

#include<bits/stdc++.h>
#define il inline
#define vd void
typedef long long ll;
il int gi(){
int x=0;
char ch=getchar();
while(!isdigit(ch)){
ch=getchar();
}
while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
return x;
}
ll A[1001],B[1001];
bool f[810][810];
ll g[810],sg[810]; il void chkmax(ll &a,ll b){if (a<b)a=b;} int main(){
register int n=gi(),i,l,r,s;
for(i=1;i<=n;++i)A[i]=gi();
for(i=1;i<=n;++i)B[i]=gi()+B[i-1];
for(i=1;i<n;++i)if(std::__gcd(A[i],A[i+1])!=1)f[i][i+1]=1;
for(s=4;s<=n;s+=2)
for(l=1;l+s-1<=n;++l){
r=l+s-1;
if(std::__gcd(A[l],A[r])!=1&&f[l+1][r-1])f[l][r]=1;
for(i=l+1;i<=r&&!f[l][r];i+=2)
f[l][r]|=f[l][i]&f[i+1][r];
}
for(r=1;r<=n;++r){//依次加入右端点为r的区间
// g[r]表示区间[1,r]的最大收益,sg[r]=max(g[1],...,g[r])
for(l=1;l<=r;++l)if(f[l][r])chkmax(g[r],B[r]-B[l-1]+sg[l-1]);
for(i=1;i<=r;++i)sg[i]=std::max(sg[i-1],g[i]);
}
printf("%lld\n",sg[n]);
return 0;
}

洛谷NOIp热身赛题解的更多相关文章

  1. 洛谷NOIp热身赛 T2123 数列游戏

    题目背景 此题为改编题,特别鸣谢倪星宇同学. 有一次,HKE和LJC在玩一个游戏. 题目描述 游戏的规则是这样的:LJC在纸上写下两个长度均为N的数列A和B,两个数列一一对应.HKE每次可以找两个相邻 ...

  2. 洛谷P2827 蚯蚓 题解

    洛谷P2827 蚯蚓 题解 题目描述 本题中,我们将用符号 ⌊c⌋ 表示对 c 向下取整. 蛐蛐国最近蚯蚓成灾了!隔壁跳蚤国的跳蚤也拿蚯蚓们没办法,蛐蛐国王只好去请神刀手来帮他们消灭蚯蚓. 蛐蛐国里现 ...

  3. 洛谷P1816 忠诚 题解

    洛谷P1816 忠诚 题解 题目描述 老管家是一个聪明能干的人.他为财主工作了整整10年,财主为了让自已账目更加清楚.要求管家每天记k次账,由于管家聪明能干,因而管家总是让财主十分满意.但是由于一些人 ...

  4. NOIP 2016 洛谷 P2827 蚯蚓 题解

    题目传送门 展开 题目描述 本题中,我们将用符号[c]表示对c向下取整,例如:[3.0」= [3.1」=[3.9」=3.蛐蛐国最近蚯蚓成灾了!隔壁跳 蚤国的跳蚤也拿蚯蚓们没办法,蛐蛐国王只好去请神刀手 ...

  5. [POI 2008&洛谷P3467]PLA-Postering 题解(单调栈)

    [POI 2008&洛谷P3467]PLA-Postering Description Byteburg市东边的建筑都是以旧结构形式建造的:建筑互相紧挨着,之间没有空间.它们共同形成了一条长长 ...

  6. [NOI 2020 Online] 入门组T1 文具采购(洛谷 P6188)题解

    原题传送门 题目部分:(来自于考试题面,经整理) [题目描述] 小明的班上共有 n 元班费,同学们准备使用班费集体购买 3 种物品: 1.圆规,每个 7 元. 2.笔,每支 4 元. 3.笔记本,每本 ...

  7. [洛谷P3948]数据结构 题解(差分)

    [洛谷P3948]数据结构 Description 最开始的数组每个元素都是0 给出n,opt ,min,max,mod 在int范围内 A: L ,R ,X 表示把[l,R] 这个区间加上X(数组的 ...

  8. [CodePlus 2017 11月赛&洛谷P4058]木材 题解(二分答案)

    [CodePlus 2017 11月赛&洛谷P4058]木材 Description 有 n棵树,初始时每棵树的高度为 Hi ,第 i棵树每月都会长高 Ai.现在有个木料长度总量为 S的订单, ...

  9. 洛谷P1189 SEARCH 题解 迭代加深

    题目链接:https://www.luogu.com.cn/problem/P1189 题目大意: 给你一个 \(n \times m\) 的矩阵,其中有一些格子可以走,一些各自不能走,然后有一个点是 ...

随机推荐

  1. 12 Things Developers Will Love About Oracle Database 12c Release 2

    by Chris Saxon-Oracle It's Here: Oracle Database 12c Release 2 (12.2) Is available on Oracle Cloud. ...

  2. 固定UIScrollView滑动的方向

    固定UIScrollView滑动的方向 一般而言,我们通过这两个参数CGRectMake以及contentSize就可以自动的让UIScrollView只往一个方向滚动.但我遇到过非常奇葩的情况,那就 ...

  3. javascript改写 <select>checked的选中,并不会出发change事件,太好了!

    <html> <title>测试select标签的分别用程序checked.用户手动checked</title> <body> 第一级菜单: < ...

  4. saltstack-把执行结果存储到mysql服务内

    saltstack把执行的结果保存到mysql中,以便进行命令安全审计 mysql负责存储数据,mysql-python负责收集数据 master需要安装mysql和MySQL-python,mini ...

  5. September 04th 2017 Week 36th Monday

    Try not to become a man of success but rather try to become a man of value. 不要努力去做一个成功的人,而要努力去做一个有价值 ...

  6. 获取索引--------用range()和len()

    a = ['Google', 'Baidu', 'Runoob', 'Taobao', 'QQ'] for i in range(len(a)): print(i+1,a[i])

  7. MFC调试时可以,使用生产的exe时,显示未响应解决方案

    首先,使用release模式,生成解决方案和exe. 对生成的exe,选择属性,兼容性,win7,应用,即可解决. 此方法对debug无用

  8. 关于markdown格式的测试..

    标题 标题一 这是? 标题二 标题三 标题四 区块 1.这是一个列表项目 还是吗? 嵌套了? 空格了? 区块加列表 标题加二级列表 嘿嘿 无序列表 RED GREEN BLUE 有序列表 dog ca ...

  9. UE4中的AI行为树简单介绍

    UE4引擎中可以实现简单AI的方式有很多,行为树是其中比较常用也很实用的AI控制方式,在官网的学习文档中也有最简单的目标跟踪AI操作教程,笔者在这里只作简单介绍. AIController->和 ...

  10. BM求递推式模板

    时间复杂度\(O(N^2)\),原理不明...... #include <cstdio> #include <cstring> #include <cmath> # ...