2021.9.21考试总结[NOIP模拟58]
T1 lesson5!
开始以为是个无向图,直接不懂,跳去T2了。
之后有看了一眼发现可暴力,于是有了\(80pts\)。
发现这个图是有拓扑序的,于是可以用拓扑排序找最长路径。先找原图内在最长路径上的点,挨个删了跑拓扑排,看哪个最短。
正解太nb了待补。
\(code:\)
80pts
#include<bits/stdc++.h>
using namespace std;
namespace IO{
inline int read(){
char ch=getchar(); int x=0,f=1;
while(ch<'0'||ch>'9'){ if(ch=='-') f=-1; ch=getchar(); }
while(ch>='0'&&ch<='9'){ x=(x<<1)+(x<<3)+(ch^48); ch=getchar(); }
return x*f;
}
inline void write(int x,char sp){
char ch[20]; int len=0;
if(x<0){ putchar('-'); x=~x+1; }
do{ ch[len++]=(1<<4)+(1<<5)+x%10; x/=10; }while(x);
for(int i=len-1;~i;--i) putchar(ch[i]); putchar(sp);
}
inline int max(int x,int y){ return x<y?y:x; }
inline int min(int x,int y){ return x<y?x:y; }
inline void swap(int& x,int& y){ x^=y^=x^=y; }
inline void ckmax(int& x,int y){ x=x<y?y:x; }
inline void ckmin(int& x,int y){ x=x<y?x:y; }
} using namespace IO;
const int NN=1e5+5,MM=5e5+5;
int t,n,m,mx,ans,pos,ban,idx,to[MM],nex[MM],head[NN],dis[NN],pre[NN];
int l,r,q[NN],in[NN],deg[NN];
bool vis[NN];
vector<int>vec;
inline void add(int a,int b){
to[++idx]=b; nex[idx]=head[a]; head[a]=idx; ++in[b];
}
void topo(){
l=1; r=0;
for(int i=1;i<=n;i++)
if(!in[i]&&ban!=i) pre[i]=0, dis[i]=0, q[++r]=i;
while(l<=r){
int x=q[l++];
if(dis[x]>mx) mx=dis[x];
for(int i=head[x];i;i=nex[i]) if(in[to[i]]&&ban!=to[i]){
--in[to[i]];
if(!in[to[i]]){
pre[to[i]]=x;
dis[to[i]]=dis[x]+1;
q[++r]=to[i];
}
}
}
}
signed main(){
FILE *R=freopen("johnny.in","r",stdin);
FILE *W=freopen("johnny.out","w",stdout);
t=read();
while(t--){
n=read(); m=read();
mx=ban=idx=0; vec.clear();
for(int i=1;i<=n;i++) in[i]=head[i]=vis[i]=0;
for(int a,b,i=1;i<=m;i++)
a=read(),b=read(), add(a,b);
for(int i=1;i<=n;i++) deg[i]=in[i];
topo(); ans=mx; pos=INT_MAX;
for(int i=1;i<=n;i++) if(dis[i]==mx){
int x=i;
while(x) vec.push_back(x), x=pre[x];
}
for(int i=0;i<vec.size();i++) if(!vis[vec[i]]){
ban=vec[i]; mx=0; vis[ban]=1;
for(int j=1;j<=n;j++) in[j]=deg[j];
for(int j=head[ban];j;j=nex[j]) --in[to[j]];
topo();
if(mx<ans||(mx==ans&&ban<pos)) ans=mx, pos=ban;
}
write(pos,' '); write(ans,'\n');
}
}
T2 贝尔数
模数不是质数就很搞。。
发现分解质因数后模数是五个一次的两位质数相乘,题目还给了模质数意义下的同余公式,于是可以先求出模五个质数意义下这一位贝尔数的值,然后再用中国剩余定理解个同余方程合并即可。
对每个质数可以先预处理前四十多个贝尔数,然后矩阵加速递推。
个人认为挺神的题(主要是数学跟矩阵都太菜了
\(code:\)
T2
#include<bits/stdc++.h>
#define int long long
using namespace std;
namespace IO{
inline int read(){
char ch=getchar(); int x=0,f=1;
while(ch<'0'||ch>'9'){ if(ch=='-') f=-1; ch=getchar(); }
while(ch>='0'&&ch<='9'){ x=(x<<1)+(x<<3)+(ch^48); ch=getchar(); }
return x*f;
}
inline void write(int x,char sp){
char ch[20]; int len=0;
if(x<0){ putchar('-'); x=~x+1; }
do{ ch[len++]=(1<<4)+(1<<5)+x%10; x/=10; }while(x);
for(int i=len-1;~i;--i) putchar(ch[i]); putchar(sp);
}
inline int max(int x,int y){ return x<y?y:x; }
inline int min(int x,int y){ return x<y?x:y; }
inline void swap(int& x,int& y){ x^=y^=x^=y; }
inline void ckmax(int& x,int y){ x=x<y?y:x; }
inline void ckmin(int& x,int y){ x=x<y?x:y; }
} using namespace IO;
const int NN=1010,mod=95041567;
int T,n,nul,c[50][50],bell[50],pre[6],calc[6];
int pri[6]={0,31,37,41,43,47};
namespace Crt{
int exgcd(int a,int b,int& x,int& y){
if(!b){
x=1; y=0;
return a;
}
int g=exgcd(b,a%b,x,y),z;
z=y; y=x-a/b*y; x=z;
return g;
}
void init(){
bell[0]=1;
for(int i=0;i<50;i++) c[i][0]=1;
for(int i=1;i<50;i++) for(int j=1;j<=i;j++)
c[i][j]=(c[i-1][j]+c[i-1][j-1])%mod;
for(int i=1;i<50;i++) for(int j=0;j< i;j++)
(bell[i]+=c[i-1][j]*bell[j]%mod)%=mod;
for(int i=1;i<6;i++){
int g=exgcd(pri[i],mod/pri[i],nul,pre[i]);
pre[i]=(pre[i]%mod+mod)%mod; pre[i]=(mod/pri[i])*pre[i]%mod;
}
}
int solve(){
int res=0;
for(int i=1;i<6;i++) (res+=pre[i]*calc[i])%=mod;
return res;
}
} using namespace Crt;
namespace Matrix{
struct matrix{
int s[50][50];
void clr(){ memset(s,0,sizeof(s)); }
void pre(){ clr(); for(int i=0;i<50;i++) s[i][i]=1; }
void print(){for(int i=0;i<50;++i)for(int j=0;j<50;++j)write(s[i][j],j==49?'\n':' ');}
}mat[6],base[6];
matrix mul(matrix x,matrix y,int z){
matrix res; res.clr();
for(int i=0;i<50;i++)
for(int k=0;k<50;k++)
for(int j=0;j<50;j++)
(res.s[i][j]+=x.s[i][k]*y.s[k][j]%z)%=z;
return res;
}
void qpow(matrix& a,matrix b,int c,int d){
while(c){
if(c&1) a=mul(a,b,d);
b=mul(b,b,d);
c>>=1;
}
}
void prework(){
for(int i=1;i<6;i++){
for(int j=0;j<pri[i];j++) mat[i].s[1][j]=bell[j]%pri[i];
base[i].pre();
base[i].s[1][0]=base[i].s[0][pri[i]-1]=base[i].s[1][pri[i]-1]=1;
for(int j=1;j<pri[i]-1;j++) base[i].s[j+1][j]=1;
}
}
} using namespace Matrix;
signed main(){
FILE *R=freopen("bell.in","r",stdin);
FILE *W=freopen("bell.out","w",stdout);
T=read(); init();
while(T--){
n=read(); prework();
for(int i=1;i<6;i++){
qpow(mat[i],base[i],n/pri[i],pri[i]);
calc[i]=mat[i].s[1][n%pri[i]];
}
write(solve(),'\n');
}
return 0;
}
T3 穿越广场
考完后发现这好像是个AC自动机套路题,但奈何时间久远,学的时候写的太快没多思考总结,于是SB了。
设\(f_{i,j,k,l}\)为\(DP\)到第\(i\)位,填了\(j\)个\(R\),在自动机中走到第\(k\)个节点,结束状态为\(l\)的方案数。
\(l\)为二进制状态,有两位。
于是有
\(\huge{f_{i,j,k,l} \to f_{i+1,j,to[k]['D'],l|end[to[k]['D']]}}\)
\(\huge{f_{i,j,k,l} \to f_{i+1,j+1,to[k]['R'],l|end[to[k]['R']]}}\)
初始状态\(f_{0,0,1,0}=1\)。
注意每个点继承它\(fail\)的状态即可。
\(code:\)
T3
#include<bits/stdc++.h>
#define int long long
#define ULL unsigned long long
using namespace std;
namespace IO{
inline int read(){
char ch=getchar(); int x=0,f=1;
while(ch<'0'||ch>'9'){ if(ch=='-') f=-1; ch=getchar(); }
while(ch>='0'&&ch<='9'){ x=(x<<1)+(x<<3)+(ch^48); ch=getchar(); }
return x*f;
}
inline void write(int x,char sp){
char ch[20]; int len=0;
if(x<0){ putchar('-'); x=~x+1; }
do{ ch[len++]=(1<<4)+(1<<5)+x%10; x/=10; }while(x);
for(int i=len-1;~i;--i) putchar(ch[i]); putchar(sp);
}
inline int max(int x,int y){ return x<y?y:x; }
inline int min(int x,int y){ return x<y?x:y; }
inline void swap(int& x,int& y){ x^=y^=x^=y; }
inline void ckmax(int& x,int y){ x=x<y?y:x; }
inline void ckmin(int& x,int y){ x=x<y?x:y; }
} using namespace IO;
const int NN=110,p=1e9+7;
int t,n,m,ext,ans,f[NN<<1][NN][NN<<1][4];
char ch[NN];
namespace AC_automaton{
int root,tot,to[NN<<1][2],fail[NN<<1],end[NN<<1];
void insert(char *s){
int len=strlen(s),u=1;
for(int i=0;i<len;i++){
int now=(s[i]=='R');
if(!to[u][now]) to[u][now]=++tot, end[tot]=0;
u=to[u][now];
}
end[u]=root?2:1;
if(!root) root=1;
}
void build(){
queue<int>q;
if(to[root][0]) q.push(to[root][0]), fail[to[root][0]]=root;
else to[root][0]=root;
if(to[root][1]) q.push(to[root][1]), fail[to[root][1]]=root;
else to[root][1]=root;
while(!q.empty()){
int u=q.front(); q.pop();
end[u]|=end[fail[u]];
if(to[u][0]) fail[to[u][0]]=to[fail[u]][0], q.push(to[u][0]);
else to[u][0]=to[fail[u]][0];
if(to[u][1]) fail[to[u][1]]=to[fail[u]][1], q.push(to[u][1]);
else to[u][1]=to[fail[u]][1];
}
}
} using namespace AC_automaton;
signed main(){
FILE *R=freopen("square.in","r",stdin);
FILE *W=freopen("square.out","w",stdout);
t=read();
while(t--){
m=read(); n=read(); tot=1; root=0; ext=n+m; ans=0;
memset(f,0,sizeof(f));
memset(to,0,sizeof(to));
memset(fail,0,sizeof(fail));
scanf("%s",ch); insert(ch);
scanf("%s",ch); insert(ch);
build(); f[0][0][1][0]=1;
for(int i=0;i<ext;i++)
for(int j=0;j<=m;j++){
if(j>i||i-j>n) continue;
for(int k=1;k<=tot;k++)
for(int u=0;u<4;u++){
(f[i+1][j ][to[k][0]][u|end[to[k][0]]]+=f[i][j][k][u])%=p;
(f[i+1][j+1][to[k][1]][u|end[to[k][1]]]+=f[i][j][k][u])%=p;
}
}
for(int i=1;i<=tot;i++) (ans+=f[ext][m][i][3])%=p;
write(ans,'\n');
}
return 0;
}
T4 舞动的夜晚
先跑最大流,然后在残量网络上跑\(tarjan\),如果边在\(SCC\)里说明它没有影响。
改的有点ex,待补
2021.9.21考试总结[NOIP模拟58]的更多相关文章
- 2021.8.21考试总结[NOIP模拟45]
T1 打表 由归纳法可以发现其实就是所有情况的总和. $\frac{\sum_{j=1}^{1<<k}(v_j-v_{ans})}{2^k}$ $code:$ 1 #include< ...
- 2021.7.21考试总结[NOIP模拟22]
终于碾压小熠了乐死了 T1 d 小贪心一波直接出正解,没啥好说的(bushi 好像可以主席树暴力找,但我怎么可能会呢?好像可以堆优化简单找,但我怎么可能想得到呢? 那怎么办?昨天两道单调指针加桶,我直 ...
- 2021.9.17考试总结[NOIP模拟55]
有的考试表面上自称NOIP模拟,背地里却是绍兴一中NOI模拟 吓得我直接文件打错 T1 Skip 设状态$f_i$为最后一次选$i$在$i$时的最优解.有$f_i=max_{j<i}[f_j+a ...
- 2021.9.13考试总结[NOIP模拟52]
T1 路径 考虑每一位的贡献,第$i$位每$2^i$个数会变一次,那么答案为$\sum_{i=1}^{log_2n} \frac{n}{2^i}$. $code:$ 1 #include<bit ...
- 2021.8.11考试总结[NOIP模拟36]
T1 Dove玩扑克 考场并查集加树状数组加桶期望$65pts$实际$80pts$,考后多开个数组记哪些数出现过,只扫出现过的数就切了.用$set$维护可以把被删没的数去掉,更快. $code:$ 1 ...
- 2021.7.29考试总结[NOIP模拟27]
T1 牛半仙的妹子图 做法挺多的,可以最小生成树或者最短路,复杂度O(cq),c是颜色数. 我考场上想到了原来做过的一道题影子,就用了并查集,把边权排序后一个个插入,记录权值的前缀和,复杂度mlogm ...
- 2021.7.15考试总结[NOIP模拟16]
ZJ模拟D2就是NB.. T1 Star Way To Heaven 谁能想到这竟是个最小生成树呢?(T1挂分100的高人JYF就在我身边 把上边界和下边界看成一个点和星星跑最小生成树,从上边界开始跑 ...
- 2021.9.14考试总结[NOIP模拟53]
T1 ZYB和售货机 容易发现把每个物品都买成$1$是没有影响的. 然后考虑最后一个物品的方案,如果从$f_i$向$i$连边,发现每个点有一个出度多个入度,可以先默认每个物品都能买且最大获利,这样可以 ...
- 2021.9.12考试总结[NOIP模拟51]
T1 茅山道术 仔细观察发现对于每个点只考虑它前面第一个与它颜色相同的点即可. 又仔细观察发现对一段区间染色后以这个区间内点为端点的区间不能染色. 于是对区间右端点而言,区间染色的贡献为遍历到区间左端 ...
随机推荐
- Docker入门之image篇
基本概念 Image 镜像:只读模板 Container 容器:从镜像创建的运行实例 Repository 仓库:集中存放镜像文件的场所.分为公开仓库(Public)和私有仓库(Private)两种形 ...
- 数据结构(c++)(第二版) Dijkstra最短路径算法 教学示范代码出现重大问题!
前言 去年在数据结构(c++)的Dijkstra教学算法案例中,发现了一个 bug 导致算法不能正常的运行,出错代码只是4行的for循环迭代代码. 看到那里就觉得有问题,但书中只给了关键代码的部分,其 ...
- 以人为本打造“超职季”IP,58同城精准匹配企业招聘与打工人
撰文 |懂懂 编辑 | 秦言 来源:懂懂笔记 在大手笔培育IP的背后,58同城是如何考量的? 在餐厅当服务员的李阿姨今年54岁了.她的女儿马上研究生毕业,非常喜欢陈伟霆,手机屏保都是他.李阿姨没想到, ...
- 使用dubbo-go搭建dubbo接口测试平台
背景 http接口测试只需要一个curl命令,但dubbo协议没有这样的现成接口测试工具.通常公司内的dubbo控制台或其他平台会集成一个dubbo接口测试工具. 调用一个dubbo接口,需要知道服务 ...
- go案例:客户管理系统流程 mvc模式 分层设计
下面是一个简要的客服系统,主要是演示分层计.. model : 数据部份: package model import "fmt" //声明一个结构体,表示一个客户信息 type C ...
- HDU 6170 FFF at Valentine(强联通缩点+拓扑排序)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6165 题意:给你一个无环,无重边的有向图,问你任意两点,是否存在路径使得其中一点能到达另一点 解析:强 ...
- 洛谷P1160——队列安排(双向链表)
题目描述 一个学校里老师要将班上N个同学排成一列,同学被编号为1-N,他采取如下的方法: 1.先将1号同学安排进队列,这时队列中只有他一个人: 2.2-N号同学依次入列,编号为i的同学入列方式为:老师 ...
- Java基础系列(29)- 方法的重载
方法的重载 重载就是在一个类中,有相同的函数名称,但形参不同的函数 方法重载的规则: 方法名称必须相同 参数列表必须不同(个数不同.或类型不同.参数排列顺序不同等) 方法的返回类型可以相同也可以不相同 ...
- centos7.X 系统初始化>>优化
1 修改网卡为eth0 cd /etc/sysconfig/network-scripts/ vim ifcfg-eno16777729TYPE=EthernetBOOTPROTO=staticIPA ...
- P4831-Scarlet loves WenHuaKe【组合数学】
正题 题目链接:https://www.luogu.com.cn/problem/P4831 题目大意 \(n*m\)的网格上放置\(2n\)个炮,要求互不能攻击. 数据满足\(n\leq m\leq ...