NOIP2018提高组模拟题(五)
字符串(string)
Description
小林与亮亮正在做一个游戏。小林随意地写出一个字符串,字符串只由大写 字母组成,然后指定一个非负整数 m,亮亮可以进行至多 m 次操作,每次操作 为交换相邻两个字符。亮亮的目标是使得操作后的字符串出现最长相同的字符的 长度最大。你能帮亮亮计算一下这个最大长度是多少吗?
Input
第一行一个字符串 S。 第二行一个整数 m。
Output
只有一个整数,表示所求的最大长度。
表示刚开始想了一个小时的\(DP\)
然后还出样例了,
要不是手出了一组样例就凉了
然后还有20分钟的时候,发现是个贪心+递归
将两侧的向中间移动显然更优.
容易发现,同种字母移动才会产生影响.
因此直接枚举每种字母,记录其位置.
由于从某一位置到目标位置的交换次数可求.所以这样是可做的.
\(\color{red}{官方题解}\)表示没看太懂
考察内容:字符串、枚举与贪心
字符串长度不超过 50,我们就可以枚举哪一个字符不动,其他相同字符向它靠近,左 右两边相同字符计算出它们与选定字符相邻需要移动几次,以此为关键值从小到大排序,贪心地处理即可。
代码
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#define R register
using namespace std;
inline void in(int &x)
{
int f=1;x=0;char s=getchar();
while(!isdigit(s)){if(s=='-')f=-1;s=getchar();}
while(isdigit(s)){x=x*10+s-'0';s=getchar();}
x*=f;
}
int ans,m,n;
int pos[833];
char s[833];
inline int cs(char s)
{
return s-'A'+1;
}
inline int calc(int l,int r)
{
if(l==r)return 0;
if(l==r-1)return pos[r]-pos[l]-1;
return calc(l+1,r-1)+pos[r]-pos[l]-(r-l);
}
int main()
{
freopen("string.in","r",stdin);
freopen("string.out","w",stdout);
scanf("%s",s+1);in(m);n=strlen(s+1);
for(R int i=1;i<=26;i++)
{
int tmp=0;
for(R int j=1;j<=n;j++)
if(cs(s[j])==i)pos[++tmp]=j;
if(tmp==1){ans=max(ans,1);continue;}
int now=-2147483644;
for(R int j=1;j<=tmp;j++)
for(R int l=j+1;l<=tmp;l++)
if(calc(j,l)<=m)
now=max(now,l-j+1);
ans=max(ans,now);
}
printf("%d",ans);
fclose(stdin);
fclose(stdout);
return 0;
}
桃园之礼(peach)
Description
小林和亮亮在桃园里一起玩游戏。桃园里的桃树成行成列,刚好构成一个 N ×M 的矩阵,亮亮在某些桃树下放置了一些小礼物,要求小林把所有树下的礼 物全部收集起来。 小林从左上角的桃树(1,1)出发,走到右下角的桃树(N,M)。他 只能沿着路径向下或者向右走,某些桃树下有礼物,他必须到达所有有礼物的树 下并把礼物收集起来。 小林在出发前,想请你帮他计算一下,他有多少种不同的 走法。由于答案可能很大,你只需要输出答案模 100000000(10^8)后的值即可。
Input
第一行三个整数 N,M 和 K。 N,M 表示矩阵的大小, K 表示有礼物的桃树的 棵数。
接下来 k 行,每行两个整数 X,Y,表示一棵有礼物的桃树的坐标(X,Y)
Output
只有一个整数,表示不同的走法数模 100000000 后的值。
刚开始没看懂题.
首先不考虑中间的有礼物的树.
我们就是求解从\((1,1)\)到\((n,m)\)的走法.
有这么多种
\]
因为我们只可能会走\(n+m-2\)步,而我们必须要选择\(m-1\)步走横向.
这\(m-1\)步随便选.即\(C_{n+m-2}^{m-1}\),
当然也可以是
\]
然后就是将大的矩形拆成小的矩形了.,
比如,如果一些地方有礼物的树.,我们就可以拆成这些子矩形。
然后我们求解子矩形从左上角到右下角的方案数.
根据乘法原理累乘即可.
注意判无解的情况!!!(被卡了\(10pts\))
这题恶心就恶心在模数不是一个质数.
我们可以考虑质因数分解来求解.
这里就不过多解释如何质因数分解了,相信大家能看懂代码的.
\(\color{red}{官方题解}\)
考察算法:质因数分解(或逆元+中国剩余定理)、排列组合
根据乘法原理,问题可以分解为求在一个 n*m 的矩形中,从左上角走到右下角共有几 种走法。显然答案为 \(C_{n+m-2}^{m-1}\) 。我们既可以用分解质因数的方法来计算,也可以采用求逆元 与中国剩余定理的方法来处理除法
代码
#include<cstdio>
#include<iostream>
#include<algorithm>
#define N 10008
#define mod 100000000
#define R register
#define int long long
using namespace std;
inline void in(int &x)
{
int f=1;x=0;char s=getchar();
while(!isdigit(s)){if(s=='-')f=-1;s=getchar();}
while(isdigit(s)){x=x*10+s-'0';s=getchar();}
x*=f;
}
int n,m,k,ans=1,cur;
struct cod{int x,y;}t[10008];
bool vis[60008];
int prime[60008],cnt,f[60008];
inline void pri()
{
for (R int i=2;i<=n+m;i++)
{
if (!vis[i]) prime[++cnt] = i;
for (R int j=1;j<=cnt and i*prime[j]<=n+m;j++)
{
vis[i*prime[j]]=true;
if (i%prime[j]==0) break;
}
}
}
inline int ksm(int x,int &y)//这里加&,可以达到memset的效果.
{
R int res=1;
for(;y;y>>=1,x=x*x%mod)
if(y&1)res=res*x%mod;
return res;
}
inline void calc(int x,int v)
{
for (R int i=1;i<=cnt and prime[i]<=x;i++)
while(x%prime[i]==0)f[i]+=v,x/=prime[i];
cur=cur*x%mod;
}
inline int C(int x,int y)
{
if (y>x) return 0;
cur=1;
for(R int i=x-y+1;i<=x;i++) calc(i,1);
for(R int i=1;i<=y;i++) calc(i,-1);
for(R int i=1;i<=cnt and prime[i]<=x;i++)
(cur*=ksm(prime[i],f[i]))%=mod;
return cur;
}
inline bool ccp(const cod&a,const cod&b)
{
if(a.x==b.x)return a.y<b.y;
return a.x<b.x;
}
signed main()
{
freopen("peach.in","r",stdin);
freopen("peach.out","w",stdout);
in(n),in(m),in(k);pri();
t[1].x=t[1].y=1;
for(R int i=2;i<=k+1;i++)
in(t[i].x),in(t[i].y);
t[2+k].x=n,t[2+k].y=m;
sort(t+1,t+k+3,ccp);
for(R int i=2;i<=k+2;i++)
{
int nn=t[i].x-t[i-1].x+1,mm=t[i].y-t[i-1].y+1;
if(nn<=0 or mm<=0)//判无解
{
puts("0");
return 0;
}
(ans*=C(nn+mm-2,mm-1))%=mod;
}
printf("%lld",ans);
fclose(stdin);
fclose(stdout);
return 0;
}
魔法森林(forest)
Description
亮亮在梦中游历了魔法城堡后,对此心驰神往,于是用自己制造的法杖,创 造了一片魔法森林。
这片森林中一开始有 n 个节点,没有边相连,若想要在第 i 个点和第 j 个点 之间建立一条双向通路,则需花 费 Cij 的魔法值。
每个结点上住着一个魔法居民,若两个节点间有边直接相连,则他们就成为 了邻居。居民一共有三种类型:
①村民:他们只能通过道路拜访自己的邻居。
②巫师:他们可以拜访自己的邻居以及邻居的邻居。
③大魔法师:由于他们拥有法力,因此可以拜访所有与自己连通的人。
亮亮不希望有人孤单,因此他保证了每种类型的居民要么不出现,否则至少 出现两个。同时,他又希望大家能建立良好的关系,所以他决定花费魔法值为魔 法森林修路,使得任意居民都可以拜访其他所有的居民。
他想知道,最少需要建立多少条道路才能达成自己的心愿。在道路数目最少 的前提下,花费的魔法值最小又是多少。
Input
第一行有一个整数 n。
第二行有 n 个整数, 第 i 个整数表示 i 号节点所居住的居民的类型(1 表示 村民, 2 表示巫师, 3 表示大魔法师) 。
接下来 n 行,每行 n 个数,是一个 n*n 的矩阵 Cij。数据保证 Cij = Cji, Cii=0。
Output
一行两个整数, 分别表示最小道路数和最小魔法值。
这里就不多BB了,官方题解写的挺好.
\(\color{red}{官方题解}\)
考察算法:分类讨论、图论
①存在第一类点的情况
此时,显然要从每个第一类点向其它点连边。 我们发现这样是满足要求的,因为这样一来,每个第二类点都可以通过第一步到达 一个第一类点来访问所有点,并且整个图显然也是连通的。 直接模拟即可。
②只存在第三类点的情况
此时,目的是使所有点连通。也就是一个最小生成树问题。 使用 \(Prim\) 或 \(Kruskal\) 在 \(O(N^2)\)或 \(O(N^2logN)\)中解决。
③其他情况
这就是说,存在第二类点,另外只可能存在第三类点。 我们取一个点,从这个点向其它点各连一条边,构成一个 star。 我们发现 star 是一棵树,且直径≤2,所以是满足要求的。 从而,第一问“最小边数”的答案为 N-1。 下面将对第二类点的数目进行讨论:
③a 恰两个
此时,若选择让两个第二类点成为邻居,那么其他的点可以在两个第二类点中选择一个费用小的连过去。 否则,这两个点的距离=2,那么就是说这两个点有一个公共邻居 u。显然其他 的点都只能连到 u 上,这样一来就构成了一个以 u 为中心的 star。枚举所有 star 即可。
③b 超过两个
由于边数是 N-1,因此至少有一对第二类点不是邻居。
这样一来就成了③a的第二种情况,枚举所有 star 即可。
最后的结论是:首先枚举所有 star 取最小费用,然后如果第二类点的数目为 2, 再考虑这两个点直接相连时的特殊情况即可。
代码
#include<cstdio>
#include<iostream>
#include<algorithm>
#define R register
using namespace std;
inline void in(int &x)
{
int f=1;x=0;char s=getchar();
while(!isdigit(s)){if(s=='-')f=-1;s=getchar();}
while(isdigit(s)){x=x*10+s-'0';s=getchar();}
x*=f;
}
int n,v[2580],tot,f[2580],mnn=4;
bool flg;
int res[258][258];
struct cod{int u,v,w;}edge[80008];
inline bool ccp(const cod&a,const cod&b)
{
return a.w<b.w;
}
int find(int x){return f[x]==x?x:f[x]=find(f[x]);}
inline void mofashi()
{
int cnt=0,ans=0;
for(R int i=1;i<=n;i++)f[i]=i;
for(R int i=1;i<=n;i++)
for(R int j=1,x;j<=n;j++)
{
in(x);
if(i>=j and x)
{
edge[++tot].u=i;
edge[tot].v=j;
edge[tot].w=x;
}
}
sort(edge+1,edge+tot+1,ccp);
for(R int i=1;i<=tot;i++)
{
R int u=edge[i].u,v=edge[i].v,w=edge[i].w;
R int fu=find(u),fv=find(v);
if(fu==fv)continue;
cnt++;ans+=w;f[fu]=fv;
if(cnt==n-1)break;
}
printf("%d\n%d\n",cnt,ans);
}
int main()
{
freopen("forest.in","r",stdin);
freopen("forest.out","w",stdout);
in(n);
for(R int i=1;i<=n;i++)in(v[i]),mnn=min(v[i],mnn);
if(mnn==1)
{
for(R int i=1;i<=n;i++)
for(R int j=1;j<=n;j++)
in(res[i][j]);
long long ans=0;
int cnt=0;
for(R int i=1;i<=n;i++)
for(R int j=i+1;j<=n;j++)
if(v[i]==1 or v[j]==1)
cnt++,ans+=res[i][j];
printf("%d %lld\n",cnt,ans);
return 0;
}
if(mnn==2)
{
for(R int i=1;i<=n;i++)
for(R int j=1;j<=n;j++)
in(res[i][j]);
int tot2=0,pa=-1,pb=-1;
for(R int i=1;i<=n;i++)
if(v[i]==2)tot2++;
long long ans=21474836476666LL;
if(tot2==2)
{
for(R int i=1;i<=n;i++)
{
if(v[i]==2)
{
if(pa==-1)
pa=i;
else
pb=i;
}
}
ans=res[pa][pb];
for(R int i=1;i<=n;i++)
ans+=min(res[i][pa],res[i][pb]);
}
for(R int i=1;i<=n;i++)
{
long long rs=0;
for(R int j=1;j<=n;j++)
rs+=res[i][j];
ans=min(ans,rs);
}
printf("%d %lld",n-1,ans);
}
if(mnn==3)mofashi();
fclose(stdin);
fclose(stdout);
return 0;
}
NOIP2018提高组模拟题(五)的更多相关文章
- 2019.6.21 NOIP2018提高组模拟题(二)
1.咒语 (curse.pas/c/cpp) [题目描述] 亮亮梦到自己来到了魔法城堡,但一扇巨大的石门阻拦了他通向城堡内的路.正当他沮丧之际,突然发现门上有一处机关,机关上有一张很长的纸条.亮亮拿起 ...
- NOIP2018提高组模拟题(四)
能量(energy) Description 有一块能量田,它的形状是 n*m的矩形,每一个格子上都有一个能量值 a[x][y] (可正可负).一块矩形田的能量定义为它的每个格子的能量值之和. ...
- NOIP2018提高组模拟题(六)
购物(shop) Description 小林来到商店中进行购物.商店里一共有 n 件物品,第 i 件物品的价格为 a[i] 元.小林总共需要购买 m 件物品,他希望他所花费的钱最少,请你计算出最小 ...
- 10.18 NOIP2018提高组模拟题(二)
大水题 1.咒语 (curse.pas/c/cpp) [题目描述] 亮亮梦到自己来到了魔法城堡,但一扇巨大的石门阻拦了他通向城堡内的路.正当他沮丧之际,突然发现门上有一处机关,机关上有一张很长的纸条. ...
- NOIP2018提高组模拟题(二)
咒语(curse) Description 亮亮梦到自己来到了魔法城堡,但一扇巨大的石门阻拦了他通向城堡内的路. 正当他沮丧之际,突然发现门上有一处机关,机关上有一张很长的纸条. 亮亮拿起纸条的一端, ...
- 11.5NOIP2018提高组模拟题
书信(letter) Description 有 n 个小朋友, 编号为 1 到 n, 他们每人写了一封信, 放到了一个信箱里, 接下来每个人从中抽取一封书信. 显然, 这样一共有 n!种拿到书信的情 ...
- [JZOJ 5852] [NOIP2018提高组模拟9.6] 相交 解题报告 (倍增+LCA)
题目链接: http://172.16.0.132/senior/#main/show/5852 题目: 题目大意: 多组询问,每次询问树上两条链是否相交 题解: 两条链相交并且仅当某一条链的两个端点 ...
- [JZOJ 5875] [NOIP2018提高组模拟9.20] 听我说,海蜗牛 解题报告(BFS+二分)
题目链接: http://172.16.0.132/senior/#main/show/5875 题目: 题解: 注意这题只能经过开放的港口 我们考虑用vector存下每个点不能到的点,并把并让vec ...
- XJOI——NOIP2015提高组模拟题19-day1——观光旅行
http://www.hzxjhs.com:83/contest/493/problem/3 [题目大意] 给定一个有n(n<=500000)个点,m(1<=500000)条边的无向图.给 ...
随机推荐
- CLion 终于支持 jump outside closing bracket/quote with Tab 了!
我觉得这个 feature 真的很有用.一直期待 CLion 加上这个 feature.今天才知道最新版本(CLion 2018.3.4)中已经有这个功能了,不过我不清楚从哪个版本开始支持的. How ...
- [bzoj4860] [BeiJing2017]树的难题
Description 给你一棵 n 个点的无根树.树上的每条边具有颜色. 一共有 m 种颜色,编号为 1 到 m.第 i 种颜色的权值为 ci.对于一条树上的简单路径,路径上经过的所有边按顺序组成一 ...
- [CF912B]New Year's Eve
题意:在1~n中选不超过m个数,求其异或最大值 题解:经过找规律发现如果m为1,输出n,不然输出最小的不超过n的2^k-1 C++ Code: #include<cstdio> using ...
- JQuery中的each()的使用
each()函数是基本上所有的框架都提供了的一个工具类函数,通过它,你可以遍历对象.数组的属性值并进行处理. jQuery和jQuery对象都实现了该方法,对于jQuery对象,只是把each方法简单 ...
- Kafka自我学习1-Multi-broker cluster
====================================Testing environment =========================================== ...
- java消息中间件入门
消息中间件来解耦服务调用 比如1个登录系统,登录的话需要调用很多系统的其他服务,如果中间调用失败,可能会导致登录信息一致无法返回,同时也增加了系统的耦合度.而用消息中间件的话,则是不发送服务到其他系统 ...
- Topcoder SRM 607 div1题解
好久没来写了,继续继续... Easy(250pts): //前方请注意,样例中带有zyz,高能预警... 题目大意:给你一个字符串,中间有一些是未知字符,请你求出这个字符串的回文子串个数的期望值.数 ...
- DOM读取和修改节点对象属性
一.获取和修改元素间的内容(3种) 1.innerHTML 获得/设置元素开始标签和结束标签之间的html原文 固定套路:1.删除父元素下所有子元素:parent.innerHTML="&q ...
- 解决Idea Jsp <%%>中 request resopnse等无自动提示的问题
解决办法:缺少Apache的lib依赖, 只需 File->Project Srructure->Libraries 加号 找到Apache安装的lib目录添加依赖即可.亲测可用
- Android 全面插件化 RePlugin 流程与源码解析
转自 Android 全面插件化 RePlugin 流程与源码解析 RePlugin,360开源的全面插件化框架,按照官网说的,其目的是“尽可能多的让模块变成插件”,并在很稳定的前提下,尽可能像开发普 ...