[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 ...
随机推荐
- zenoss(智能监控软件)
Zenoss Core是开源企业级IT管理软件-是智能监控软件,他允许IT管理员依靠单一的WEB控制台来监控网络架构的状态和健康度,同时也是开源的网络与系统管理软件.全名 Zenos ...
- fiddler使用笔记1
转载地址:写得很不错的fildder教程 http://kb.cnblogs.com/page/130367/ Fiddler的基本介绍 Fiddler的官方网站: www.fiddler2.c ...
- [CSP-S模拟测试]:water(BFS)
题目描述 有一块矩形土地被划分成$n\times m$个正方形小块.这些小块高低不平,每一小块都有自己的高度.水流可以由任意一块地流向周围四个方向的四块地中,但是不能直接流入对角相连的小块中.一场大雨 ...
- Majordomo Info VGER.KERNEL.ORG
This is VGER.KERNEL.ORG Majordomo Info The mission of vger.kernel.org is to provide email list servi ...
- Qt文件夹遍历
void FindFile(const QString &_filepath) { QDir dir(_filepath); for each (QFileInfo mfile in dir. ...
- java并发编程笔记(十一)——高并发处理思路和手段
java并发编程笔记(十一)--高并发处理思路和手段 扩容 垂直扩容(纵向扩展):提高系统部件能力 水平扩容(横向扩容):增加更多系统成员来实现 缓存 缓存特征 命中率:命中数/(命中数+没有命中数) ...
- SQL语言分类DDL、DML、DQL、TCL、DCL
关系型数据库的SQL语句都可以分为4大类: 1. DDL(数据定义语言) DDL 主要是指如下的四种SQL 语句,以 CREATE.DROP.ALRET开头和 TRUNCATE TABLE 语 ...
- Problem accessing /jenkins/. Reason:
这是一个Jenkins的Bug.临时解决方法是:在浏览器中手工输入:http://<ip>:<port>.不要访问"/jenkins"这个路径.
- phpStorm debug
1.重点注意(重要) 如果是wamp,那么请通过wamp打开php.ini文件,不要自己去找php文件夹下的php.ini,这是两个不同的文件 2.开始配置php.ini zend_extension ...
- Selenium:三种等待方式详解
我们在做WEB自动化时,一般要等待页面元素加载完成后,才能执行操作,否则会报找不到元素的错误,这样就要求我们在有些场景下加等待时间. 我们平常用到的有三种等待方式: 强制等待 隐式等待 显示等待 一. ...