爆零了。少特判见祖宗。还好这场不计入总分。

考场上什么都没想。感觉考试状态又回到了两个月前。

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]题解的更多相关文章

  1. CSP-S 模拟测试94题解

    T1 yuuustu: 可以对两边取对数,然后就转化为两个double的比较,时间复杂度$O(n)$ 然后我就用神奇0.4骗分水过 #include<bits/stdc++.h> usin ...

  2. CSP-S模拟测试 88 题解

    T1 queue: 考场写出dp柿子后觉得很斜率优化,然后因为理解错了题觉得斜率优化完全不可做,只打了暴力. 实际上他是可以乱序的,所以直接sort,正确性比较显然,贪心可证,然后就是个sb斜率优化d ...

  3. CSP-S 模拟测试92 题解

    话说我怎么觉得我没咕多长时间啊,怎么就又落了20多场题解啊 T1 array: 根据题意不难列出二元一次方程,于是可以用exgcd求解,然而还有一个限制条件就是$abs(x)+abs(y)$最小,这好 ...

  4. CSP-S 模拟测试57题解

    人生第一次A,B层一块考rank2,虽然说分差没几分,但还是值得纪念. 题解: T1 天空龙: 大神题,因为我从不写快读也没有写考场注释的习惯,所以不会做,全hzoi就kx会做,kx真大神级人物. T ...

  5. CSP-S 模拟测试 51 题解

    考试过程: 惯例先看一遍三道题,T1 一开始反应要求割点,但是这是有向图,肯定不能求割点,康了一下数据范围,有40%是树的,还不错,决定待会在打. 看T2 字符串题,完了我字符串最弱了,肯定只能打暴力 ...

  6. CSP-S 模拟测试 45 题解

    由于咕掉的题解太多了,所以只能趁改完不动题的时间,来补补坑qwq,还是太弱了. 考试过程: 到新机房的第一次考试,貌似海星? 第一题一开始就觉得是个贪心,但以为所有小怪兽都要打完,所以想复杂了,但后来 ...

  7. [CSP-S模拟测试97]题解

    A.小盆友的游戏 感觉题解解释的很牵强啊……还是打表找规律比较靠谱 对于每个人,它构造了一个期望函数$f(x)$,设它的跟班个数为$cnt[x]$,那么令$f(x)=2^{cnt[x]}-1$(??鬼 ...

  8. [CSP-S模拟测试96]题解

    以后不能再借没改完题的理由不写题解了…… A.求和 求$\sum \sum i+j-1$ 柿子就不化了吧……这年头pj都不考这么弱智的公式化简了…… 坑点1:模数不定,可能没有2的逆元,那么只要先把乘 ...

  9. [CSP-S模拟测试92]题解

    A.数列 显然每个数的答案是互相独立的,直接扩欧求解.我们需要最小化$ax+by=gcd(a,b)$中的$|x|+|y|$,而显然当x或y靠近0时答案可能最优,列个不等式求一下即可. 能$O(1)$千 ...

  10. [CSP-S模拟测试86]题解

    好久没有写整套题的题解了呢……主要是这两天考试题愈发神仙 实在是超出了垃圾博主的能力范围啊QAQ A.异或 不难想到,如果我们得到了$[L,R]$中每一位上0和1的个数,那么答案即为$2 \times ...

随机推荐

  1. SQLserver查询作业、视图、函数、存储过程中的关键字

    一.查询视图.函数.存储过程中的关键字 SELECT a.name,a.[type],b.[definition] FROM sys.all_objects a,sys.sql_modules b W ...

  2. cordova打包apk流程

    一.打包 条件: 1.java-jdk 2.Android-sdk  ( 安装教程:https://blog.csdn.net/qq_36577136/article/details/80632674 ...

  3. error C2872: ‘ofstream’ : ambiguous symbol

    转自VC错误:http://www.vcerror.com/?p=1123 问题描述: 编译时出现: error C2872: 'ofstream' : ambiguous symbol error ...

  4. linux 组合命令

    统计home目录下面有多少文件 ls -l  /home|grep '^-'|wc -l

  5. Map-Amap:货运解决方案

    ylbtech-Map-Amap:货运解决方案 1.返回顶部 1. http://lbs.amap.com/smart/truck/ 2. 2.返回顶部 1. 2. 3.返回顶部   4.返回顶部   ...

  6. Shiro那些事儿(一): Shiro初探

    引言 权限,可以简单的理解成你能干什么,不能干什么.在管理系统中,对权限的设计可以很简单,也可以很复杂.简单点的,基本都是基于角色扮演的方式,比如系统管理员角色可以操作哪些菜单,普通用户角色可以操作哪 ...

  7. 移动H5优化指南

    转载于http://isux.tencent.com/h5-performance.html 移动H5前端性能优化指南 概述 秒完成或使用Loading4. 基于联通3G网络平均338KB/s(2.7 ...

  8. selenium,webdriver,xpath获取全国各地的邮编

    代码要多敲 注释要清晰 其中区号没有拿取出来 看到的朋友可以作为练习 ,有好的方法可以在下面留言 from selenium import webdriver from lxml import etr ...

  9. tensorflow|tf.train.slice_input_producer|tf.train.Coordinator|tf.train.start_queue_runners

    #### ''' tf.train.slice_input_producer :定义样本放入文件名队列的方式[迭代次数,是否乱序],但此时文件名队列还没有真正写入数据 slice_input_prod ...

  10. SSH服务搭建、账号密码登录远程Linux虚拟机、基于密钥的安全验证(Windows_Xshell,Linux)

    问题1:如果是两台虚拟机ping不同且其中一个虚拟机是克隆的另一个,需要更改一下MAC地址,关机状态下 一> "编辑虚拟机设置" 一>" 网络适配器" ...