状态极差的两场。感觉现在自己的思维方式很是有问题。

(但愿今天考试开始的一刻我不会看到H I J)

A

考场上打了最短路+贪心,水了60。

然而正解其实比那30分贪心好想多了。

进行n次乘法后的结果一定可以化成$S\times b^n + m\times a$的形式,并且$m$是b的若干次幂(带系数)之和。

也就是说,$m=\frac{T-S\times b^n}{a}$可以写成$b$进制数,当然前提是$T-S \times b^n \ mod\ a=0$。

那么这个b进制数的系数之和其实就是加法操作的次数,这个很好理解。

枚举乘法次数,然后得到相应的$m$后直接$b$进制拆解,注意要从高次开始。

#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
typedef long long ll;
ll S,T,a,b,ans=1e15;
int main()
{
scanf("%lld%lld%lld%lld",&S,&T,&a,&b);
for(ll n=0,now=1;S*now<=T;n++,now*=b)
{
ll m=T-S*now,res=0;
if(m%a)continue;
m/=a;
ll c=now;
while(m)res+=m/c,m%=c,c/=b;
res+=n;
ans=min(ans,res);
}
cout<<ans<<endl;
return 0;
}

B.

首先可以想到一个比较暴力的dp:$f[i][j]$表示前$i$个变量乘积为$j$的方案数,枚举上一个结果和当前变量的值$O(p^2)$转移即可。

正解只理解了思想,但转移方程仍然不是很懂。

打表很容易发现一个性质:若$gcd(a,P)=gcd(b,P)$,那么$f[i][a]=f[i][b]$。

显然出题人居心叵测,把两个状态转移方程的条件写反了23333。

不过话说$\varphi(\frac{P}{a})$的含义是$a$能代表的数,那方程里为什么要再$\times a$呢?辣鸡博主不是很明白。

C.

设特殊加速器的使用次数为$x$,总费用为$y$,那么$y$关于$x$的函数显然是单谷的,所以可以三分。

考虑如何在已知$x$的情况下快速求出费用。可以对每个点预处理包含它的区间的最右端点,这个直接开个数组对每个$l_i$标记一下就行。

每次计算的时候用差分的思想实现区间减法,不过直接暴力循环似乎也可过??

#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
int read()
{
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;
}
const int N=1e5+5;
typedef long long ll;
int n,m,t,a[N],s[N],L[N],R[N],rm[N],maxh,p[N],v[N];
ll ans=1e15;
ll cacl(int x)
{
for(int i=1;i<=n;i++)
p[i]=max(0,a[i]-x);
ll res=1LL*t*x;
int yet=0;
for(int i=1;i<=n;i++)
{
yet-=v[i];v[i]=0;
p[i]=max(0,p[i]-yet);
res+=p[i];
yet+=p[i];
v[rm[i]+1]+=p[i];
}
return res;
} int main()
{
//freopen("9.in","r",stdin);
n=read();m=read();t=read();
for(int i=1;i<=n;i++)
a[i]=read(),maxh=max(maxh,a[i]);
for(int i=1;i<=m;i++)
{
L[i]=read();R[i]=read();
s[L[i]]=max(s[L[i]],R[i]);
}
int now=0;
for(int i=1;i<=n;i++)
{
if(s[i])now=max(now,s[i]);
rm[i]=now;
if(now==i)now=0;
}
int l=0,r=maxh;
for(int i=1;i<=n;i++)
if(!rm[i])l=max(l,a[i]);
//cout<<l<<endl;
while(l<=r)
{
int mid1=l+(r-l)/3,mid2=l+(r-l)*2/3;
ll val1=cacl(mid1),val2=cacl(mid2);
if(val1>=val2)l=mid1+1,ans=min(ans,val2);
else r=mid2-1,ans=min(ans,val1); }
cout<<ans<<endl;
return 0;
}

D.

暴力的基础上加个剪枝就可以。考虑极限情况,如果当前的$gcd$乘上$(n-i+1)$都没法更新ans($i$为枚举的左端点),那么直接break即可。

实测卡不掉。zkt巨巨证了复杂度,可以做到$O(n\ log\ n)$。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int n,a[100005],st[100005][21],lg[100005]={-1};
ll ans;
int read()
{
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 gcd(int x,int y)
{
if(!y)return x;
return gcd(y,x%y);
}
int main()
{
n=read();
for(int i=1;i<=n;i++)
a[i]=read();
//ini();
for(int i=1;i<=n;i++)
{
int now=a[i];
for(int j=i;j<=n;j++)
{
now=gcd(now,a[j]);
if(now==1){ans=max(ans,1LL*(n-i+1));break;}
if(1LL*now*(n-i+1)<ans)break;
ans=max(ans,1LL*(j-i+1)*now);
} } cout<<ans<<endl;
return 0;
}

E.

贪心搜索乱搞水过了。严谨的贪心抽时间补。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+5;
int n;
ll a[N][3],ans=1e15;
double tim;
void dfs(int x,ll rmax,ll rmin,ll bmax,ll bmin)
{
if(x>1&&(rmax-rmin)*(bmax-bmin)>ans)return ;
if(x>n)
{
ans=min(ans,(rmax-rmin)*(bmax-bmin));
if((clock()-tim)/1e6>=1.5)printf("%lld\n",ans),exit(0);
return ;
}
dfs(x+1,max(rmax,a[x][0]),min(rmin,a[x][0]),max(bmax,a[x][1]),min(bmin,a[x][1]));
dfs(x+1,max(rmax,a[x][1]),min(rmin,a[x][1]),max(bmax,a[x][0]),min(bmin,a[x][0]));
return ;
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
for(int j=0;j<=1;j++)
scanf("%lld",&a[i][j]);
if(a[i][0]<a[i][1])swap(a[i][0],a[i][1]);
}
tim=clock();
dfs(1,0,1e15,0,1e15);
cout<<ans<<endl;
return 0;
}

F.

线段树优化dp。

状态定义有些不好想:$f[i][j]$表示进行到第$i$次操作,一个指针在$pos[i]$(题目里给的),另一个在$j$时的最小费用。

$f[i][j]=\min (f[i-1][j]+|p_i-p_{i-1}|)$

$f[i][p[i-1]]=\min (f[i-1][j]+|p_i-j|)$

暴力转移是$O(n^2)$的。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int read()
{
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
return x*f;
}
const int N=1e5+5;
int n,q,p1,p2;
int pos[N];
ll ans=1e15,dp[2005][2005];
int abss(int x)
{
return x>0?x:-x;
}
int main()
{
n=read();q=read();p1=read();p2=read();
for(int i=1;i<=q;i++)pos[i]=read();
memset(dp,0x3f,sizeof(dp));
dp[1][p1]=abss(pos[1]-p2),dp[1][p2]=abss(pos[1]-p1);
for(int i=2;i<=q;i++)
{
for(int j=1;j<=n;j++)
dp[i][pos[i-1]]=min(dp[i-1][j]+1LL*abss(pos[i]-j),dp[i][pos[i-1]]),
dp[i][j]=min(dp[i-1][j]+1LL*abss(pos[i]-pos[i-1]),dp[i][j]); } for(int i=1;i<=n;i++)
ans=min(ans,dp[q][i]);
cout<<ans<<endl;
return 0;
}

我们注意到转移1可以用线段树区间加实现,对于转移2先拆绝对值,维护$f[i][j]+j$和$f[i][j]-j$的最小值即可。

用到的操作:区间修改,区间查询,单点修改。

注意单点修改要放在区间加后面啊!

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5;
typedef long long ll;
const ll inf=0x3f3f3f3f3f3f3f3f;
int read()
{
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
return x*f;
}
int n,q,p1,p2;
int pos[N];
ll dp[N];
int abss(int x)
{
return x>0?x:-x;
}
#define ls(k) (k)<<1
#define rs(k) (k)<<1|1
ll a[N<<2],b[N<<2],lz[N<<2];
void up(int k)
{
a[k]=min(a[ls(k)],a[rs(k)]);
b[k]=min(b[ls(k)],b[rs(k)]);
}
void down(int k,int l,int r)
{
int mid=l+r>>1;
lz[ls(k)]+=lz[k];
a[ls(k)]+=lz[k];b[ls(k)]+=lz[k];
lz[rs(k)]+=lz[k];
a[rs(k)]+=lz[k];b[rs(k)]+=lz[k];
lz[k]=0;
}
void build(int k,int l,int r)
{
if(l==r)
{
if(l==p1)a[k]=abss(pos[1]-p2)+p1,b[k]=abss(pos[1]-p2)-p1;
else if(l==p2)a[k]=abss(pos[1]-p1)+p2,b[k]=abss(pos[1]-p1)-p2;
else a[k]=b[k]=inf;
return ;
}
int mid=l+r>>1;
build(ls(k),l,mid);
build(rs(k),mid+1,r);
up(k);
}
void add(int k,int l,int r,int L,int R,ll val)
{
if(l>r)return ;
if(L<=l&&R>=r)
{
a[k]+=val;b[k]+=val;
lz[k]+=val;
return ;
}
if(lz[k])down(k,l,r);
int mid=l+r>>1;
if(L<=mid)add(ls(k),l,mid,L,R,val);
if(R<mid)add(rs(k),mid+1,r,L,R,val);
up(k);
}
void update(int k,int l,int r,int pos,ll val,int op)
{
if(l==r)
{
if(!op)a[k]=min(a[k],val);
else b[k]=min(b[k],val);
return ;
}
if(lz[k])down(k,l,r);
int mid=l+r>>1;
if(pos<=mid)update(ls(k),l,mid,pos,val,op);
else update(rs(k),mid+1,r,pos,val,op);
up(k);
} ll qmin(int k,int l,int r,int L,int R,int op)
{
if(L<=l&&R>=r)return op?b[k]:a[k];
if(lz[k])down(k,l,r);
int mid=l+r>>1;
ll res=inf;
if(L<=mid)res=min(res,qmin(ls(k),l,mid,L,R,op));
if(R>mid)res=min(res,qmin(rs(k),mid+1,r,L,R,op));
return res;
}
ll getans(int k,int l,int r)
{
if(l==r)return a[k]-l;
int mid=l+r>>1;
if(lz[k])down(k,l,r);
return min(getans(ls(k),l,mid),getans(rs(k),mid+1,r));
} int main()
{
n=read();q=read();p1=read();p2=read();
for(int i=1;i<=q;i++)pos[i]=read();
build(1,1,n);
for(int i=2;i<=q;i++)
{
ll val1=qmin(1,1,n,pos[i],n,0)-pos[i],val2=qmin(1,1,n,1,pos[i],1)+pos[i];
add(1,1,n,1,n,abss(pos[i]-pos[i-1])); update(1,1,n,pos[i-1],min(val1,val2)+pos[i-1],0);
update(1,1,n,pos[i-1],min(val1,val2)-pos[i-1],1);
}
cout<<getans(1,1,n)<<endl;
return 0;
}

[CSP模拟测试43、44]题解的更多相关文章

  1. [CSP-S模拟测试50]反思+题解

    ??大部分人都觉得T3是道不可做题去刚T1T2了,于是我就侥幸苟到了前面? 这场考试比较成功的就是快速水掉了T1T2的部分分,1h拿到88分起码为之后硬肝T3上了保险(赛后发现就算T3爆零也能rank ...

  2. csp-c模拟测试43「A·B·C」

    B 题解 $f[i][(gcd(prime[j]*prime[k]\%P,P))]=\sum\limits_{k=1}^{k<=num} f[i-1][k]*phi(\frac{P}{prime ...

  3. [考试反思]0914csp-s模拟测试43:破绽

    T1会正解.爆int了,代码里一大堆long long但是有一个地方落了.-70分. 离考试结束还有19秒的时候发现手模样例爆负数了,没来得及改. T2没想.打暴力了.然而实际很好想...早读5分钟就 ...

  4. [CSP-S模拟测试48]反思+题解

    状态很垃圾的一场考试.感觉“这么多分就够了”的心态很是在给自己拖后腿. 打开题面,第一页赫然写着:$Claris' Contest$. 吓得我差点手一抖关掉.不过后来想想似乎强到变态的人出的题都不是很 ...

  5. [CSP-S模拟测试47]反思+题解

    打开题面,T3似乎被换过了.(那我就更有理由直接弃掉了) T1是我最害怕的乱搞题,赶紧扔了看T2.发现是个sb板子?雨天的尾巴弱化版? 然而线段树合并早忘干净了(最近几道可以线段树合并的题都是用别的方 ...

  6. [NOIP模拟测试37]反思+题解

    一定要分析清楚复杂度再打!!!窝再也不要花2h20min用暴力对拍暴力啦!!! 雨露均沾(滑稽),尽量避免孤注一掷.先把暴力分拿全再回来刚正解. 即使剩下的时间不多了也优先考虑认真读题+打暴力而非乱搞 ...

  7. [NOIP模拟测试34]反思+题解

    不要陷入思维定势,如果长时间没有突破就要考虑更改大方向. 不要把简单问题复杂化. 做完的题就先放下,不管能拿多少分.不能过一段时间就回来调一下. $Solutions:$ A.次芝麻 因为$n+m$始 ...

  8. [NOIP模拟测试32]反思+题解

    又考挂了QAQ 总rank直接滑出前20 晚上考试脑子还算比较清醒,可惜都用来xjb乱想错误思路了. T1一眼推柿子,然而并没有头绪所以先码了个暴力.然后…… 一个垃圾暴力我调了1h,大概解决了两位数 ...

  9. [NOIP模拟测试7]visit 题解(组合数学+CRT+Lucas定理)

    Orz 因为有T的限制,所以不难搞出来一个$O(T^3)$的暴力dp 但我没试 据说有30分? 正解的话显然是组合数学啦 首先$n,m$可能为负,但这并没有影响, 我们可以都把它搞成正的 即都看作向右 ...

随机推荐

  1. webbench(web性能压力测试工具)

    在运维工作中,压力测试是一项很重要的工作.比如在一个网站上线之前,能承受多大访问量.在大访问量情况下性能怎样,这些数据指标好坏将会直接影响用户体验.但是,在压力测试中存在一个共性,那就是压力测试的结果 ...

  2. 回复git@vger.kernel.org的注意事项

    比如回复这封邮件 https://public-inbox.org/git/db2dcf54-8b1c-39b1-579c-425ef158c6a1@kdbg.org/ Reply instructi ...

  3. git分支回退以及目录回退

    分支回退 git checkout - 目录回退 cd -

  4. Castle动态代理拦截

    比如现在有一个方法,进行积分奖励 PointAdd 在不改变原来方法的基础上,增加积分奖励的日志 using Castle.DynamicProxy; public class AuditTraceI ...

  5. 用 Flask 来写个轻博客 (34) — 使用 Flask-RESTful 来构建 RESTful API 之三

    目录 目录 前文列表 应用请求中的参数实现 API 分页 测试 前文列表 用 Flask 来写个轻博客 (1) - 创建项目 用 Flask 来写个轻博客 (2) - Hello World! 用 F ...

  6. Asp.Net Core 第05局:读取配置

    前言 本文介绍Asp.Net Core 读取配置文件. 环境 1.Visual Studio 2017 2.Asp.Net Core 2.2 开局 前期准备             1.添加app.j ...

  7. springboot 尚桂谷学习总结02

    ------向导快速创建Springboot 项目------ 1.使用spring initializer 快速创建一个springboot 项目 选择后 最后点击finsh 向导会联网创建 spr ...

  8. 彻底干掉恶心的 SQL 注入漏洞, 一网打尽!

    来源:b1ngz.github.io/java-sql-injection-note/ 简介 文章主要内容包括: , name); 还有一些情况,比如 order by.column name,不能使 ...

  9. BZOJ 3611 大工程 (虚树)

    题面 国家有一个大工程,要给一个非常大的交通网络里建一些新的通道. 我们这个国家位置非常特殊,可以看成是一个单位边权的树,城市位于顶点上. 在 2 个国家 a,b 之间建一条新通道需要的代价为树上 a ...

  10. 高精度求A*B(FFT)

    A * B Problem Plus 链接:http://acm.hdu.edu.cn/showproblem.php?pid=1402 Time Limit: 2000/1000 MS (Java/ ...