热门标签 | HotTags
当前位置:  开发笔记 > 人工智能 > 正文

2018.08.14【2018提高组】模拟A组比赛总结

题解这次的A组难得得水。T1这题我一看,就想起了GDOI的一道题——密码锁\(O(n)\)算法——差分于是乎兴奋地发现这道题可以用差分来解。设\(f_ia_i-a_{i-1}\)。

题解

这次的A组难得得水。


T1

这题我一看,就想起了GDOI的一道题——密码锁


\(O(n)\)算法——差分

于是乎兴奋地发现这道题可以用差分来解。

设\(f_i=a_i-a_{i-1}\)。

然后就可以发现一些神奇的东西:


当\(f_i>0\)时,第i个数比第i-1个数的操作数多了\(f_i\),可以先一起+1,再给第i个数+1

当\(f_i=0\)时,第i个数与第i-1个数的操作数一样多,一起+1即可

当\(f_i<0\)时,第i个数比第i-1个数的操作数少了\(-f_i\),因此只能与它一起进行\(a_i\)次操作。


于是可以用一个维护一下每一个操作(具体见标程),考场AC!


\(O(n\log_2n)\)算法——分治+RMQ

差分的方法可能比较难理解,不过这个做法比较简单。

可以发现,对于每个区间\([l,r]\),一开始我们是可以把里面所有数+1的,直到加到\(a_{min}\)(设min为l到r的最小值),接下来就是\([l,min]\)和\([min+1,r]\)这两个区间+1。

因此,这题可以用分治来做。

但是暴力求最小值会TLE,因此要用RMQ优化一下。


T2

比赛时毫无头绪,于是乎打了一个暴力,水了45分。

为了方便,设下面所用的x数组均满足第一个条件。

设\(F(x)=\Pi_{i=1}^{2m}x_i\),如果\(F(x)n^m\),且数量等于全部的\(F(x)>n^m\)的数量。由于x'与x是一一对应的,所以\(F(x)n^m\)的方案数一样多。

设A表示\(F(x)n^m\)的方案数。显然A+B+C的值为\(\sigma(n)^{2m}\)。而我们又已经证明了A=C,所以只要求出B,就可以求出A:

\[
A =\frac{A+B+C+B}{2}\\
=\frac{\sigma(n)^{2m}+B}{2}
\]

那么B怎么求呢?

设\(n={p_1}^{c_1}\cdot{p_2}^{c_2}\cdots{p_k}^{c_k}\),其中p都为质数,且两两不同。

设\(f_{i,j}\)表示到了n的某个质因数,到了\(x_i\),已经选了j个\(p\)的方案数,这个很容易求。

最后把所有的 f 乘起来就是B了。


T3

赛时不懂样例,问DL们,不答,曰:“告诉你样例怎么求不就是白给了40分了吗?”。计算半日,无解,遂弃疗。

设\(f_i\)表示从i的子节点走到i的期望步数,\(g_i\)表示从i的父节点走到i的期望步数。

那么状态转移方程显然(其中\(deg_i\)表示i的度,\(fa_i\)表示i的父节点):

\(f_u=\frac{1}{deg_u}+\Sigma_{x\in child_u}\frac{f_x+1+f_u}{deg_u}\)

\(g_u=\frac{1}{deg_{fa_u}}+\frac{1+g_u+g_{fa_u}}{deg_{fa_u}}+\Sigma_{x\in child_{fa_u}\bigwedge x\neq u}\frac{1+g_u+fx}{deg_{fa_u}}\)

移项后,转移方程中的\(f_u,g_u\)就可以被消去了:

\[
\begin{aligned}
f_u & =\frac{1}{deg_u}+\sum_{x\in child_u}\frac{f_x+1+f_u}{deg_u}\\
f_u & =\frac{1}{deg_u}+\frac{fu(deg_u-1)}{deg_u}+\sum_{x\in child_u}\frac{f_x+1}{deg_u}\\
f_u-\frac{fu(deg_u-1)}{deg_u} & =\frac{1}{deg_u}+\sum_{x\in child_u}\frac{f_x+1}{deg_u}\\
\frac{deg_uf_u-fu(deg_u-1)}{deg_u} & =\frac{1}{deg_u}+\sum_{x\in child_u}\frac{f_x+1}{deg_u}\\
(deg_u-deg_u+1)f_u & =1+deg_u-1+\sum_{x\in child_u}f_x\\
f_u & =deg_u+\Sigma_{x\in child_u}f_x
\end{aligned}
\]

\[
\begin{aligned}
g_u & =\frac{1}{deg_{fa_u}}+\frac{1+g_u+g_{fa_u}}{deg_{fa_u}}+\sum_{x\in child_{fa_u}\bigwedge x\neq u}\frac{1+g_u+f_x}{deg_{fa_u}}\\
g_u & =\frac{2}{deg_{fa_u}}+\frac{g_u(deg_{fa_u}-1)}{deg_{fa_u}}+\frac{g_{fa_u}}{deg_{fa_u}}+\sum_{x\in child_{fa_u}\bigwedge x\neq u}\frac{1+f_x}{deg_{fa_u}}\\
\frac{(deg_{fa_u}-1)g_u}{deg_{fa_u}} & = \frac{2+g_{fa_u}+deg_{fa_u}-2}{deg_{fa_u}}+\sum_{x\in child_{fa_u}\bigwedge x\neq u}\frac{f_x}{deg_{fa_u}}\\
g_u & = deg_{fa_u}+g_{fa_u}+\sum_{x\in child_{fa_u}\bigwedge x\neq u}f_x
\end{aligned}
\]

求结果时计算u到lca的所有f的和与v到lca的所有的g的和即可。




标程

T1

#include
#include
using namespace std;
#define N 100010
struct add
{
int start,end,times;
}a[N],ans[N];
bool cmp(const add x,const add y)
{
if(x.start!=y.start) return x.start return x.end>y.end;
}
int main()
{
freopen("range.in","r",stdin);
freopen("range.out","w",stdout);
int n,i,j,now,minus,last=0,times=0,l=0,lenth=0;
scanf("%d",&n);
for(i=1;i<=n;i++)
{
scanf("%d",&now);
if(now>last)
{
times+=now-last;
a[++l]=(add){i,0,now-last};
}
else if(now {
minus=last-now;
while(a[l].times {
ans[++lenth]=(add){a[l].start,i-1,a[l].times};
minus-=a[l].times,l--;
}
ans[++lenth]=(add){a[l].start,i-1,minus};
a[l].times-=minus;
}
last=now;
}
while(l>0)
{
ans[++lenth]=(add){a[l].start,n,a[l].times};
l--;
}
printf("%d\n",times);
for(i=1;i<=lenth;i++)
for(j=1;j<=ans[i].times;j++)
printf("%d %d\n",ans[i].start,ans[i].end);
return 0;
}

T2

#include
#include
#include
using namespace std;
#define ll long long
#define mod 998244353
ll f[250][3500],n,m,p,c,tt,sum=1;
inline ll min(ll x,ll y){return xinline void dp()
{
memset(f,0,sizeof(f));
ll i,j,k;
f[0][0]=1;
for(i=1;i<=tt;i++)
for(j=0;j<=c*m;j++)
for(k=min(j,c);k>-1;k--)
f[i][j]=(f[i][j]+f[i-1][j-k])%mod;
}
inline ll power(ll x,ll y)
{
ll s=1;
while(y)
{
if(y&1) s=s*x%mod;
x=x*x%mod,y>>=1;
}
return s;
}
int main()
{
freopen("count.in","r",stdin);
freopen("count.out","w",stdout);
ll i,j,k,b=1,inv;
scanf("%lld%lld",&n,&m);
tt=m<<1;
for(i=2;i<=sqrt(n);i++)
if(n%i==0)
{
p=i,c=0;
while(n%i==0) n/=i,c++;
sum=sum*(c+1)%mod,dp();
b=b*f[tt][c*m]%mod;
}
if(n>1)
{
p=n,c=1;
sum=sum*(c+1)%mod,dp();
b=b*f[tt][c*m]%mod;
}
sum=power(sum,tt);
inv=power(2,mod-2);
printf("%lld\n",(sum+b)%mod*inv%mod);
return 0;
}

T3

#include
#include
using namespace std;
#define ll long long
#define mod 1000000007ll
#define N 100010
struct edge
{
ll end,next;
}a[N<<1];
struct node
{
ll deep,id;
}now;
priority_queuedata;
bool close[N];
ll first[N],deg[N],deep[N],f[N],g[N],fa[N][20],n,m,s;
bool operator <(const node x,const node y){return x.deepinline void inc(ll x,ll y)
{
deg[x]++,deg[y]++;
a[++s]=(edge){y,first[x]};
first[x]=s;
a[++s]=(edge){x,first[y]};
first[y]=s;
}
void makeTree(ll k,ll from)
{
fa[k][0]=from;
deep[k]=deep[from]+1;
for(ll i=first[k];i;i=a[i].next)
if(a[i].end!=from)
makeTree(a[i].end,k);
}
void countf()
{
ll i;
while(!data.empty())
{
now=data.top();
data.pop();
(f[fa[now.id][0]]+=f[now.id])%=mod;
if(!close[fa[now.id][0]])
{
close[fa[now.id][0]]=1;
data.push((node){now.deep-1,fa[now.id][0]});
}
}
}
void countg(ll k)
{
ll i,sum=0;
for(i=first[k];i;i=a[i].next)
if(a[i].end!=fa[k][0])
sum+=f[a[i].end];
for(i=first[k];i;i=a[i].next) if(a[i].end!=fa[k][0])
{
g[a[i].end]=deg[k]+g[k]+sum-f[a[i].end];
countg(a[i].end);
}
}
inline ll lca(ll u,ll v)
{
ll i,ans=0;
if(deep[u] for(i=17;i>=0;i--)
if(deep[fa[u][i]]>=deep[v])
u=fa[u][i];
if(u==v) return u;
for(i=17;i>=0;i--)
if(fa[u][i]!=fa[v][i])
u=fa[u][i],v=fa[v][i];
return fa[u][0];
}
void dfs(int k)
{
f[k]=(f[k]+f[fa[k][0]])%mod,g[k]=(g[k]+g[fa[k][0]])%mod;
for(int i=first[k];i;i=a[i].next)
if(a[i].end!=fa[k][0])
dfs(a[i].end);
}
int main()
{
freopen("tree.in","r",stdin);
freopen("tree.out","w",stdout);
ll i,j,u,v,ans;
scanf("%lld%lld",&n,&m);
for(i=1;i {
scanf("%lld%lld",&u,&v);
inc(u,v);
}
deep[0]=0;
makeTree(1,0);
for(i=2;i<=n;i++)
{
f[i]=deg[i];
if(deg[i]==1)
close[i]=1,data.push((node){deep[i],i});
}
close[0]=close[1]=1;
countf();countg(1);
dfs(1);
for(j=1;j<18;j++)
for(i=1;i<=n;i++)
fa[i][j]=fa[fa[i][j-1]][j-1];
while(m--)
{
scanf("%lld%lld",&u,&v);
i=lca(u,v);
ans=f[u]+mod-f[i]+g[v]+mod-g[i];
if(ans) printf("%lld\n",ans%mod);
else puts("0");
}
return 0;
}


推荐阅读
  • 本文详细解析了JavaScript中相称性推断的知识点,包括严厉相称和宽松相称的区别,以及范例转换的规则。针对不同类型的范例值,如差别范例值、统一类的原始范例值和统一类的复合范例值,都给出了具体的比较方法。对于宽松相称的情况,也解释了原始范例值和对象之间的比较规则。通过本文的学习,读者可以更好地理解JavaScript中相称性推断的概念和应用。 ... [详细]
  • 一、Hadoop来历Hadoop的思想来源于Google在做搜索引擎的时候出现一个很大的问题就是这么多网页我如何才能以最快的速度来搜索到,由于这个问题Google发明 ... [详细]
  • Android中高级面试必知必会,积累总结
    本文介绍了Android中高级面试的必知必会内容,并总结了相关经验。文章指出,如今的Android市场对开发人员的要求更高,需要更专业的人才。同时,文章还给出了针对Android岗位的职责和要求,并提供了简历突出的建议。 ... [详细]
  • CSS3选择器的使用方法详解,提高Web开发效率和精准度
    本文详细介绍了CSS3新增的选择器方法,包括属性选择器的使用。通过CSS3选择器,可以提高Web开发的效率和精准度,使得查找元素更加方便和快捷。同时,本文还对属性选择器的各种用法进行了详细解释,并给出了相应的代码示例。通过学习本文,读者可以更好地掌握CSS3选择器的使用方法,提升自己的Web开发能力。 ... [详细]
  • 本文介绍了Java工具类库Hutool,该工具包封装了对文件、流、加密解密、转码、正则、线程、XML等JDK方法的封装,并提供了各种Util工具类。同时,还介绍了Hutool的组件,包括动态代理、布隆过滤、缓存、定时任务等功能。该工具包可以简化Java代码,提高开发效率。 ... [详细]
  • 本文介绍了C#中生成随机数的三种方法,并分析了其中存在的问题。首先介绍了使用Random类生成随机数的默认方法,但在高并发情况下可能会出现重复的情况。接着通过循环生成了一系列随机数,进一步突显了这个问题。文章指出,随机数生成在任何编程语言中都是必备的功能,但Random类生成的随机数并不可靠。最后,提出了需要寻找其他可靠的随机数生成方法的建议。 ... [详细]
  • qt学习(六)数据库注册用户的实现方法
    本文介绍了在qt学习中实现数据库注册用户的方法,包括登录按钮按下后出现注册页面、账号可用性判断、密码格式判断、邮箱格式判断等步骤。具体实现过程包括UI设计、数据库的创建和各个模块调用数据内容。 ... [详细]
  • “你永远都不知道明天和‘公司的意外’哪个先来。”疫情期间,这是我们最战战兢兢的心情。但是显然,有些人体会不了。这份行业数据,让笔者“柠檬” ... [详细]
  • 生成对抗式网络GAN及其衍生CGAN、DCGAN、WGAN、LSGAN、BEGAN介绍
    一、GAN原理介绍学习GAN的第一篇论文当然由是IanGoodfellow于2014年发表的GenerativeAdversarialNetworks(论文下载链接arxiv:[h ... [详细]
  • [译]技术公司十年经验的职场生涯回顾
    本文是一位在技术公司工作十年的职场人士对自己职业生涯的总结回顾。她的职业规划与众不同,令人深思又有趣。其中涉及到的内容有机器学习、创新创业以及引用了女性主义者在TED演讲中的部分讲义。文章表达了对职业生涯的愿望和希望,认为人类有能力不断改善自己。 ... [详细]
  • 无线认证设置故障排除方法及注意事项
    本文介绍了解决无线认证设置故障的方法和注意事项,包括检查无线路由器工作状态、关闭手机休眠状态下的网络设置、重启路由器、更改认证类型、恢复出厂设置和手机网络设置等。通过这些方法,可以解决无线认证设置可能出现的问题,确保无线网络正常连接和上网。同时,还提供了一些注意事项,以便用户在进行无线认证设置时能够正确操作。 ... [详细]
  • 本文介绍了游戏开发中的人工智能技术,包括定性行为和非定性行为的分类。定性行为是指特定且可预测的行为,而非定性行为则具有一定程度的不确定性。其中,追逐算法是定性行为的具体实例。 ... [详细]
  • JavaScript设计模式之策略模式(Strategy Pattern)的优势及应用
    本文介绍了JavaScript设计模式之策略模式(Strategy Pattern)的定义和优势,策略模式可以避免代码中的多重判断条件,体现了开放-封闭原则。同时,策略模式的应用可以使系统的算法重复利用,避免复制粘贴。然而,策略模式也会增加策略类的数量,违反最少知识原则,需要了解各种策略类才能更好地应用于业务中。本文还以员工年终奖的计算为例,说明了策略模式的应用场景和实现方式。 ... [详细]
  • 本文介绍了PhysioNet网站提供的生理信号处理工具箱WFDB Toolbox for Matlab的安装和使用方法。通过下载并添加到Matlab路径中或直接在Matlab中输入相关内容,即可完成安装。该工具箱提供了一系列函数,可以方便地处理生理信号数据。详细的安装和使用方法可以参考本文内容。 ... [详细]
  • 本文详细介绍了相机防抖的设置方法和使用技巧,包括索尼防抖设置、VR和Stabilizer档位的选择、机身菜单设置等。同时解释了相机防抖的原理,包括电子防抖和光学防抖的区别,以及它们对画质细节的影响。此外,还提到了一些运动相机的防抖方法,如大疆的Osmo Action的Rock Steady技术。通过本文,你将更好地理解相机防抖的重要性和使用技巧,提高拍摄体验。 ... [详细]
author-avatar
柳绿海蓝
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有