[CSP-S模拟测试ex]题解
爆零了。少特判见祖宗。还好这场不计入总分。
考场上什么都没想。感觉考试状态又回到了两个月前。
A.Antipalindrome
手玩样例,不难发现题目中要求的合法串的充要条件是:对于任意$i \in [2,n]$,有$ s[i] \neq s[i-1]\ and \ s[i-1]\neq s[i+1]$
那么第一个位置有$m$种选择,第二个位置有$m-1$种,第三个位置往后都有$m-2$种。
$ans=m(m-1)(m-2)^{n-2}$
注意特判。如果判少会直接爆0。
#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
typedef long long ll;
const ll mod=1e9+7;
int T;
ll n,m;
ll qpow(ll a,ll b)
{
ll res=1;a=a%mod;
while(b)
{
if(b&1)res=res*a%mod;
a=a*a%mod;
b>>=1;
}
return res;
}
void work()
{
scanf("%lld%lld",&n,&m);
m%=mod;
if(m==1)
{
if(n==1)puts("1");
else puts("0");
return ;
}
if(n==1)
{
cout<<m<<endl;
return ;
}
ll ans=m*(m-1)%mod;
ans*=qpow(m-2,n-2),ans%=mod;
cout<<ans<<endl;
}
int main()
{
scanf("%d",&T);
while(T--)work();
return 0;
}
B.Randomwalking
明显的换根dp。设$f[x]$表示x的子树对答案的贡献,$g[x]$表示x子树之外的部分对答案的贡献。那么$f[]$可以先用一遍dfs求得,然后在换根过程中求$g[]$顺便统计答案。
设$son[x]$为x的儿子数,显然这个要对根节点特判一下。那么可得$f[x]=a[x]+\sum \frac{f[y]}{son[x]}$,y是x的儿子。
然后考虑怎么换根。设fa为x的父亲,方程为$g[x]=\frac{g[fa]+(f[fa]-a[fa])*son[fa]-f[x]}{son[fa]}+a[fa]$。
解释一下,$(f[fa]-a[fa])*son[fa]$
相当与先还原出 $\sum f[s]$ (s为fa的儿子,包括x),
然后去掉$f[x]$的贡献,把剩下的作为x外部的点重新计算入$g[x]$。
最后统计答案的时候要比较的是$\frac{g[x]+(f[x]-a[x])*son[x]}{son[x]+1}+a[x]$,也相当与一个还原的过程。
#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=1e6+5;
const double inf=9999999999999.0;
typedef long long ll;
int n,a[N];
int to[N<<1],head[N],nxt[N<<1],tot,deg[N],minn;
double dp[N],g[N],minx=inf;
void add(int x,int y)
{
to[++tot]=y;
nxt[tot]=head[x];
head[x]=tot;
deg[x]++;
}
void dfs1(int x,int f)
{
dp[x]=a[x];
int d=f?deg[x]-1:deg[x];
for(int i=head[x];i;i=nxt[i])
{
int y=to[i];
if(y==f)continue;
dfs1(y,x);
dp[x]+=dp[y]/(1.0*d);
}
}
void dfs2(int x,int f)
{
int df=(f==1?deg[f]:deg[f]-1);
g[x]=(g[f]+(dp[f]-a[f])*df-dp[x])/df+a[f];
double now=(g[x]+(dp[x]-a[x])*(deg[x]-1))/deg[x]+a[x];
if(minx>now)minx=now,minn=x;
for(int i=head[x];i;i=nxt[i])
if(to[i]!=f)dfs2(to[i],x);
}
int main()
{
n=read();
for(int i=1;i<=n;i++)
a[i]=read();
for(int i=1;i<n;i++)
{
int x=read(),y=read();
add(x,y);add(y,x);
}
dfs1(1,0);
minx=dp[1],minn=1;
for(int i=head[1];i;i=nxt[i])
dfs2(to[i],1);
cout<<minn<<endl;
return 0;
}
C.String
记录一下每个原来的位置被翻转到了哪里,用并查集维护一定相同的位置对应关系。如果一个联通块中有一个确定了,那么就都确定了。对于剩下的'?',用26进制的思想逐位填。
区间反转上Splay。卡常。
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#define re register
using namespace std; const int L=1<<20|1;
char buffer[L],*S,*T;
#define getchar() ((S==T&&(T=(S=buffer)+fread(buffer,1,L,stdin),S==T))?EOF:*S++) const int N=5e5+5,inf=0x3f3f3f3f;
typedef long long ll;
int n,m,a[N],b[N],tot,fa[N],vis[N],unsu[N],cnt;
ll K;
char str[N],s[N];
inline int rint()
{
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;
}
inline ll rll()
{
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;
}
inline void read(char x[])
{
char ch=getchar();int now=0;
while(ch!='?'&&(ch>'z'||ch<'a'))ch=getchar();
while(ch=='?'||(ch>='a'&&ch<='z'))x[++now]=ch,ch=getchar();
} int findf(int x)
{
if(fa[x]==x)return x;
return fa[x]=findf(fa[x]);
}
namespace Splay
{
int fa[N],son[N][3],size[N],key[N],v[N],type,root;
inline bool judge(int x){return son[fa[x]][1]==x;}
inline void up(int x){size[x]=size[son[x][0]]+size[son[x][1]]+1;}
inline void down(int x)
{
if(x&&v[x])
{
v[son[x][0]]^=1;v[son[x][1]]^=1;
swap(son[x][0],son[x][1]);v[x]=0;
}
}
inline void rotate(int x)
{
int old=fa[x],oldf=fa[old],lr=judge(x);
down(old);down(x);
son[old][lr]=son[x][lr^1];
fa[son[old][lr]]=old;
son[x][lr^1]=old;fa[old]=x;
fa[x]=oldf;
if(oldf)son[oldf][son[oldf][1]==old]=x;
up(old);up(x);
}
inline void splay(int x,int goal)
{
for(int f;(f=fa[x])!=goal;rotate(x))
if(fa[f]!=goal)
rotate(judge(x)==judge(f)?f:x);
if(!goal)root=x;
}
int build(int f,int l,int r)
{
if(l>r)return 0;
int mid=l+r>>1,x=++type;
key[x]=a[mid];fa[x]=f;
v[x]=0;
son[x][0]=build(x,l,mid-1);
son[x][1]=build(x,mid+1,r);
up(x);
return x;
}
inline int getrank(int x)
{
int now=root;
while(1)
{
down(now);
if(x<=size[son[now][0]])now=son[now][0];
else
{
x-=size[son[now][0]]+1;
if(!x)return now;
now=son[now][1];
}
}
}
inline void rev(int l,int r)
{
l=getrank(l),r=getrank(r+2);
splay(l,0);splay(r,l);
down(root);
v[son[son[root][1]][0]]^=1;
}
void print(int now)
{
down(now);
if(son[now][0])print(son[now][0]);
if(key[now]!=-inf&&key[now]!=inf)b[++tot]=key[now];
if(key[son[now][1]])print(son[now][1]);
}
}
int main()
{
n=rint();m=rint();K=rll();
read(str);
for(re int i=1;i<=n;i++)
fa[i]=a[i+1]=i;
a[1]=-inf;a[n+2]=inf;
Splay::root=Splay::build(0,1,n+2);
for(re int i=1;i<=m;i++)
{
int l=rint(),r=rint();
Splay::rev(l,r);
}
Splay::print(Splay::root);
/*for(int i=1;i<=n;i++)
cout<<b[i]<<' ';
puts(" ");*/
for(re int i=1;i<=n;i++)
{
int fx=findf(b[i]),fy=findf(i);
if(fx==fy)continue;
if(str[fy]=='?')str[fy]=str[fx];
fa[fx]=fy;
}
for(re int i=1;i<=n;i++)
{
int fx=findf(i);
s[i]=str[fx];
if(s[i]=='?'&&!vis[fx])vis[fx]=1,unsu[++cnt]=fx;
}
K--;int now=cnt;
while(K)
{
str[unsu[now]]='a'+K%26;
now--;
K/=26;
}
while(now>0)str[unsu[now]]='a',now--;
for(re int i=1;i<=n;i++)
{
if(s[i]=='?')s[i]=str[findf(i)];
putchar(s[i]);
}
putchar('\n');
return 0;
}
[CSP-S模拟测试ex]题解的更多相关文章
- CSP-S 模拟测试94题解
T1 yuuustu: 可以对两边取对数,然后就转化为两个double的比较,时间复杂度$O(n)$ 然后我就用神奇0.4骗分水过 #include<bits/stdc++.h> usin ...
- CSP-S模拟测试 88 题解
T1 queue: 考场写出dp柿子后觉得很斜率优化,然后因为理解错了题觉得斜率优化完全不可做,只打了暴力. 实际上他是可以乱序的,所以直接sort,正确性比较显然,贪心可证,然后就是个sb斜率优化d ...
- CSP-S 模拟测试92 题解
话说我怎么觉得我没咕多长时间啊,怎么就又落了20多场题解啊 T1 array: 根据题意不难列出二元一次方程,于是可以用exgcd求解,然而还有一个限制条件就是$abs(x)+abs(y)$最小,这好 ...
- CSP-S 模拟测试57题解
人生第一次A,B层一块考rank2,虽然说分差没几分,但还是值得纪念. 题解: T1 天空龙: 大神题,因为我从不写快读也没有写考场注释的习惯,所以不会做,全hzoi就kx会做,kx真大神级人物. T ...
- CSP-S 模拟测试 51 题解
考试过程: 惯例先看一遍三道题,T1 一开始反应要求割点,但是这是有向图,肯定不能求割点,康了一下数据范围,有40%是树的,还不错,决定待会在打. 看T2 字符串题,完了我字符串最弱了,肯定只能打暴力 ...
- CSP-S 模拟测试 45 题解
由于咕掉的题解太多了,所以只能趁改完不动题的时间,来补补坑qwq,还是太弱了. 考试过程: 到新机房的第一次考试,貌似海星? 第一题一开始就觉得是个贪心,但以为所有小怪兽都要打完,所以想复杂了,但后来 ...
- [CSP-S模拟测试97]题解
A.小盆友的游戏 感觉题解解释的很牵强啊……还是打表找规律比较靠谱 对于每个人,它构造了一个期望函数$f(x)$,设它的跟班个数为$cnt[x]$,那么令$f(x)=2^{cnt[x]}-1$(??鬼 ...
- [CSP-S模拟测试96]题解
以后不能再借没改完题的理由不写题解了…… A.求和 求$\sum \sum i+j-1$ 柿子就不化了吧……这年头pj都不考这么弱智的公式化简了…… 坑点1:模数不定,可能没有2的逆元,那么只要先把乘 ...
- [CSP-S模拟测试92]题解
A.数列 显然每个数的答案是互相独立的,直接扩欧求解.我们需要最小化$ax+by=gcd(a,b)$中的$|x|+|y|$,而显然当x或y靠近0时答案可能最优,列个不等式求一下即可. 能$O(1)$千 ...
- [CSP-S模拟测试86]题解
好久没有写整套题的题解了呢……主要是这两天考试题愈发神仙 实在是超出了垃圾博主的能力范围啊QAQ A.异或 不难想到,如果我们得到了$[L,R]$中每一位上0和1的个数,那么答案即为$2 \times ...
随机推荐
- 解决修改 Linux 下的 PHP 环境变量不生效的方法
这个问题出现服务器有多个 PHP 版本,php -v和phpinfo()显示两个不同的版本 最近真的,都给朋友解决问题了... phpinfo查看的 php 版本是 7.2.6,到 bash 去使用p ...
- QTP-创建一个word文件
'创建word实例 Set oWordApp = CreateObject("Word.Application") oWordApp.Visible =True '添加一个word ...
- Chrome 强行修改配置
大约有两个月没写了,一是最近这两个月还挺忙,更重要的是也没有遇到什么好玩的,或者是要记录的,今天无意间遇到一个非技术问题:Chrome设置的问题. 问题描述: chrome 在下载文件时,默认情况下是 ...
- 简单DP入门(二) 最长上升子序列及其优化
最长上升子序列解决问题: 有N个数,求出它最长的上升子序列并输出长度. 在题里不会讲的这么直白,这个算法往往会与其他的算法混在一起使用. 在这篇文章中不会出现其他的例题,为了让大家更好的理解,我只会对 ...
- QTP 保留对象
1. 常用保留对象(Utility Objects) 保留对象:所谓QTP保留对象就是QTP本身预留的一些可用对象. 通俗些讲就是,当打开QTP时它就已经把这些对象给实例化了,直到关闭QTP后,这些保 ...
- jmeter工作原理介绍,以及常见错误
JMeter结果树响应数据中文乱码解决办法 打开jmeter配置文件搜索encoding修改编码格式改为utf-8 Jmeter服务器反馈登陆不成功问题 导入到JMeter后,执行场景,发现登录校验成 ...
- canvas 踩坑记录
一.绘制一个带有多张图片和文字的canvas.要求将一张矩形的图片,放置进去显示为圆角矩形的图片 解决方案,先把图片处理成圆角矩形的样子,再放进去就可以了 绘制圆角矩形图片的解决方案 效果如下图 &l ...
- asciinema.org -Record Your Terminal Share it with no fuss
紀錄 Terminal 下指令的過程 http://asciinema.org/
- nginx之域名重定向
一般网站默认的访问端口为80,当多个域名指向同一个服务器IP时,可以nginx进行重定向,分别指向不同的目的地址或其他主机. 在nginx目录下的conf/vhost子目录下建两个conf文件,hos ...
- 背包九讲(Orz)
P01: 01背包问题 题目 有\(N\)件物品和一个容量为\(V\)的背包.第\(i\)件物品的费用是\(c[i]\),价值是\(w[i]\).求解将哪些物品装入背包可使这些物品的费用总和不超过背包 ...