Loading

Noip模拟58 2021.9.21(中秋祭&&换机房祭)

第一次在学校过中秋节,给家里人视频电话,感觉快回家了很开心,

然后还吃了汉堡喝饮料非常爽,颓废了一会儿还换了新机房,$Linux2.0$非常dei,少爷机也非常快,

发现好像测评机又成了老爷机,这就是信息领域的更新速度吗??

T1 Lesson5!

咕咕咕

T2 贝尔数

原先见过这种东西,但是这道题确实用不上。。。

考虑利用题目里面给的公式来做

1.$Bell_{n+1}=\sum_{k=0}^{n}C_{n}^{k}*Bell_{k}$

2.$Bell_{n+p}\equiv Bell_{n+1}+Bell_{n}(mod\ p) (p \in prime)$ Touchard同余公式

我们发现题目里面给的模数是几个质数相乘,那么考虑中国剩余定理,算出每个关于质数模数的答案然后合并

而考场上忘记如何打$CRT$在此止步了。。。更惨的是贪了一波空间不小心给爆内存了,直接送掉$50$分,可恶

以后开数组可要小心点,尤其是$longlong$的数组

关于质数模数的直接使用两个公式即可算出,然后为了快一点可以考虑使用矩阵加速转移,建出的转移矩阵需要满足同余公式的规律

 1 #include<bits/stdc++.h>
 2 #define int long long
 3 using namespace std;
 4 namespace AE86{
 5     inline int read(){
 6         int x=0,f=1;char ch=getchar();
 7         while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
 8         while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}return x*f;
 9     }inline void write(int x,char opt='\n'){
10         char ch[20];int len=0;if(x<0)x=~x+1,putchar('-');
11         do{ch[len++]=x%10+(1<<5)+(1<<4);x/=10;}while(x);
12         for(register int i=len-1;i>=0;--i)putchar(ch[i]);putchar(opt);}
13 }using namespace AE86;
14 
15 const int NN=100,mod=95041567;
16 int T,n,m;
17 
18 int B[NN],C[NN][NN];
19 inline void work(){
20     C[0][0]=1;
21     for(int i=1;i<=50;i++){ C[i][0]=C[i][i]=1;
22         for(int j=1;j<i;j++) C[i][j]=(C[i-1][j-1]+C[i-1][j])%mod;
23     } B[0]=1;
24     for(int i=1;i<=50;i++) for(int j=0;j<i;j++)
25         B[i]=(B[i]+C[i-1][j]*B[j]%mod)%mod;
26 }
27 
28 int mi[10]={0,31,37,41,43,47},M=95041567,x,y;
29 inline int EXgcd(int a,int b,int& x,int& y){
30     if(!b){ x=1; y=0; return a;}
31     int gcd=EXgcd(b,a%b,x,y);
32     int t=x; x=y; y=t-y*(a/b);
33     return gcd;
34 }
35 
36 namespace Matrix{
37     int p[NN],c[NN][NN];
38     struct Ma{
39         int m[NN];
40         int mm[NN][NN];
41     }s[10];
42     inline void mul(int a[NN],int b[NN][NN],int mo){
43         memset(p,0,sizeof(p));
44         for(int i=0;i<=mo-1;i++)
45             for(int j=0;j<=mo-1;j++)
46                 p[i]=(p[i]+a[j]*b[j][i]%mod)%mod;
47         memcpy(a,p,sizeof(p));
48     }
49     inline void mulself(int a[NN][NN],int mo){
50         memset(c,0,sizeof(c));
51         for(int i=0;i<=mo-1;i++)
52             for(int j=0;j<=mo-1;j++)
53                 for(int k=0;k<=mo-1;k++)
54                     c[i][j]=(c[i][j]+a[i][k]*a[k][j]%mod)%mod;
55         memcpy(a,c,sizeof(c));
56     }
57     inline void prework(){
58         for(int i=1;i<=5;i++) for(int j=0;j<mi[i];j++) s[i].m[j]=B[j]%mi[i];
59         for(int i=1;i<=5;i++){
60             int tmp=0;
61             for(int j=0;j<mi[i];j++){
62                 if(j==0) s[i].mm[mi[i]-1][j]=1;
63                 else s[i].mm[tmp][j]=1,s[i].mm[tmp+1][j]=1,++tmp;
64             }
65         }
66     }
67 }using namespace Matrix;
68 
69 namespace WSN{
70     inline short main(){
71         freopen("bell.in","r",stdin);
72         freopen("bell.out","w",stdout);
73         T=read(); work();
74         while(T--){
75             int n=read(),ans=0;
76             for(int i=1;i<=5;i++) memset(s[i].m,0,sizeof(s[i].m)),memset(s[i].mm,0,sizeof(s[i].mm));
77             prework();
78             for(int i=1;i<=5;i++){
79                 int cnt=n/(mi[i]-1);
80                 while(cnt){
81                     if(cnt&1) mul(s[i].m,s[i].mm,mi[i]);
82                     cnt>>=1; mulself(s[i].mm,mi[i]);
83                 }
84                 int Mi=M/mi[i],gcd=EXgcd(Mi,mi[i],x,y);
85                 int ti=(x%mi[i]+mi[i])%mi[i];
86                 ans=(ans+s[i].m[n%(mi[i]-1)]*ti%mod*Mi%mod)%mod;
87             }
88             write(ans);
89         }
90         return 0;
91     }
92 }
93 signed main(){return WSN::main();}
View Code

 

T3 穿越广场

比较神仙的$AC$自动机+$dp$,考场上想到用自动机,但没想出如何设计$dp$,等于啥也不会

只有两个子串,那么我们设计四个状态$0,1,2,3$分别表示:

不包含任意一个串

包含第一个串

包含第二个串

包含两个串

那么设$f[i][j][k][l]$表示走到第$i$步,使用了$j$个$R$,走到了$trie$上的第$k$个节点,状态为$l$的方案数

那么边界是$f[0][0][root][0]=1$,终点是$\sum f[n+m][m][i][3]$

 1 #include<bits/stdc++.h>
 2 #define int long long
 3 using namespace std;
 4 namespace AE86{
 5     inline int read(){
 6         int x=0,f=1;char ch=getchar();
 7         while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
 8         while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}return x*f;
 9     }inline void write(int x,char opt='\n'){
10         char ch[20];int len=0;if(x<0)x=~x+1,putchar('-');
11         do{ch[len++]=x%10+(1<<5)+(1<<4);x/=10;}while(x);
12         for(register int i=len-1;i>=0;--i)putchar(ch[i]);putchar(opt);}
13 }using namespace AE86;
14 
15 const int NN=105,mod=1e9+7;
16 int T,n,m;
17 char s[NN];
18 queue<int> q;
19 namespace AC_JJ{
20     int tot,tr[NN<<1][2],fail[NN<<1],tag[NN<<1];
21     inline void insert(char *s,int id){
22         int len=strlen(s+1),u=0;
23         for(int i=1;i<=len;i++){
24             int ch=(s[i]=='D'?0:1);
25             if(!tr[u][ch]) tr[u][ch]=++tot;
26             u=tr[u][ch];
27         } tag[u]|=id;
28     }
29     inline void getfail(){
30         fail[0]=0;
31         for(int i=0;i<2;i++)
32             if(tr[0][i]) q.push(tr[0][i]),fail[tr[0][i]]=0;
33             else tr[0][i]=0;
34         while(!q.empty()){
35             int u=q.front(); q.pop();
36             if(tag[fail[u]]) tag[u]|=tag[fail[u]];
37             for(int i=0;i<2;i++){
38                 if(tr[u][i]) fail[tr[u][i]]=tr[fail[u]][i],q.push(tr[u][i]);
39                 else tr[u][i]=tr[fail[u]][i];
40             }
41         }
42     }
43 }using namespace AC_JJ;
44 int f[NN<<1][NN][NN<<1][4];
45 namespace WSN{
46     inline short main(){
47         freopen("square.in","r",stdin);
48         freopen("square.out","w",stdout);
49         T=read();
50         while(T--){
51             m=read(); n=read(); tot=0;
52             memset(f,0,sizeof(f));
53             memset(tr,0,sizeof(tr));
54             memset(tag,0,sizeof(tag));
55             memset(fail,0,sizeof(fail));
56             scanf("%s",s+1); insert(s,1);
57             scanf("%s",s+1); insert(s,2);
58             getfail(); f[0][0][0][0]=1;
59             for(int i=0;i<n+m;i++){
60                 for(int j=0;j<=m;j++){
61                     if(j>i||i-j>n) continue;
62                     for(int k=0;k<=tot;k++){
63                         for(int l=0;l<4;l++){
64                             (f[i+1][j  ][tr[k][0]][l|tag[tr[k][0]]]+=f[i][j][k][l])%=mod;
65                             (f[i+1][j+1][tr[k][1]][l|tag[tr[k][1]]]+=f[i][j][k][l])%=mod;
66                         }
67                     }
68                 }
69             }
70             int ans=0;
71             for(int i=0;i<=tot;i++) ans=(ans+f[n+m][m][i][3])%mod;
72             write(ans);
73         }
74         return 0;
75     }
76 }
77 signed main(){return WSN::main();}
View Code

 

T4  舞动的夜晚

这是我见过的最长的图论题

 

 拿到第五杀

考场上$yy$出了半正解,但是少连接了几条关键的边导致从$50->0$?

 1 #include<bits/stdc++.h>
 2 #define int long long
 3 using namespace std;
 4 namespace AE86{
 5     inline int read(){
 6         int x=0,f=1;char ch=getchar();
 7         while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
 8         while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}return x*f;
 9     }inline void write(int x,char opt='\n'){
10         char ch[20];int len=0;if(x<0)x=~x+1,putchar('-');
11         do{ch[len++]=x%10+(1<<5)+(1<<4);x/=10;}while(x);
12         for(register int i=len-1;i>=0;--i)putchar(ch[i]);putchar(opt);}
13 }using namespace AE86;
14 
15 const int NN=1e5+5,inf=0x7fffffff,mod=1e9+7;
16 int n,m,TT;
17 struct bian{int u,v;}p[NN];
18 struct SNOW{int fr,to,val,next;}e[NN<<1];int head[NN],rp=1;
19 inline void add(int x,int y,int z){
20     e[++rp]=(SNOW){x,y,z,head[x]};head[x]=rp;
21     e[++rp]=(SNOW){y,x,0,head[y]};head[y]=rp;
22 }
23 
24 int S,T,dis[NN],HD[NN],q[NN],h,t,maxnflow;
25 inline bool bfs(){
26     memset(dis,0x3f,sizeof(dis));
27     memcpy(head,HD,sizeof(head));
28     q[h=t=1]=S; dis[S]=0;
29     while(h<=t){
30         int x=q[h++];
31         for(int i=head[x];i;i=e[i].next) if(e[i].val)
32             if(dis[e[i].to]>dis[x]+1)
33                 dis[e[i].to]=dis[x]+1,q[++t]=e[i].to;
34         if(x==T) return 1;
35     }return 0;
36 }
37 inline int dfs(int x,int in){
38     if(x==T) return in;
39     int rest=in,go;
40     for(int i=head[x];i;head[x]=i=e[i].next) if(e[i].val){
41         int y=e[i].to,v=e[i].val;
42         if(dis[y]==dis[x]+1){
43             go=dfs(y,min(rest,v));
44             if(go) e[i].val-=go, e[i^1].val+=go, rest-=go;
45             else dis[y]=0;
46         }if(!rest) break;
47     }return in-rest;
48 }
49 inline int dinic(){
50     int ans=0;
51     memcpy(HD,head,sizeof(HD));
52     while(bfs()) ans+=dfs(S,inf);
53     return ans;
54 }
55 int tmp;
56 int pre[NN];
57 namespace WSN{
58     inline short main(){
59         freopen("night.in","r",stdin);
60         freopen("night.out","w",stdout);
61         n=read(); m=read(); TT=read(); //二分图匹配,网络流
62         int tot=n+m; S=++tot; T=S+1;
63         for(int i=1;i<=TT;i++) p[i].u=read(),p[i].v=read()+n;
64         for(int i=1;i<=n;i++) add(S,i,1);
65         for(int i=1;i<=m;i++) add(i+n,T,1);
66         for(int i=1;i<=TT;i++) add(p[i].u,p[i].v,1);
67         // for(int i=1;i<=rp;i++) cout<<e[i].fr<<" "<<e[i].to<<" "<<e[i].val<<endl;
68         maxnflow=dinic();
69         // cout<<maxnflow<<endl;
70         for(int i=1;i<=TT;i++){
71             memset(head,0,sizeof(head)); rp=1; int ans=0;
72             int u=p[i].u,v=p[i].v;
73             for(int j=1;j<=n;j++) if(j!=u) add(S,j,1);
74             for(int j=1;j<=m;j++) if(j+n!=v) add(j+n,T,1);
75             for(int j=1;j<=TT;j++) if(j!=i&&p[j].v!=v&&p[j].u!=u) add(p[j].u,p[j].v,1);
76             ans=dinic(); if(ans+1<maxnflow) ++tmp,pre[tmp]=i;
77         }
78         write(tmp); 
79         if(!tmp) return puts(""),0;
80         for(int i=1;i<=tmp;i++) write(pre[i],' ');
81         return 0;
82     }
83 }
84 signed main(){return WSN::main();}
T50

这种挂分都已经不再意外了,可是还是很难受

挂了一百,只剩四十。。。。

暴力考虑到了正解就不远了。暴力是网络流的板子,每次按照题意新建一张图,再和初始的图去比较一下

如果最大流加一不到原来的最大流,那就是不好的一对舞蹈组合。

正解考虑先预处理出最大流,然后根据每条边流量的变化找到一组合法的二分图匹配,记录这些边为匹配边

再使用预处理时候的残量网络,跑一遍$Tarjan$,判断每一条边是否是合法边

合法边满足以下条件:1.不是匹配边;2.边$(i,j)$在一个$SCC$里面

然后用总边数减去合法边剩下的输出即可

  1 #include<bits/stdc++.h>
  2 #define int long long
  3 using namespace std;
  4 namespace AE86{
  5     inline int read(){
  6         int x=0,f=1;char ch=getchar();
  7         while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
  8         while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}return x*f;
  9     }inline void write(int x,char opt='\n'){
 10         char ch[20];int len=0;if(x<0)x=~x+1,putchar('-');
 11         do{ch[len++]=x%10+(1<<5)+(1<<4);x/=10;}while(x);
 12         for(register int i=len-1;i>=0;--i)putchar(ch[i]);putchar(opt);}
 13 }using namespace AE86;
 14 
 15 const int NN=3e5+5,inf=0x7fffffff;
 16 
 17 int n,m,TT;
 18 struct bian{int u,v,id;}p[NN],match[NN],disma[NN];
 19 struct SNOW{
 20     int fr,to,val,next;
 21     void print(){printf("fr=%lld to=%lld\n",fr,to);}
 22 }e[NN<<1];int head[NN],rp=1;
 23 
 24 inline void add(int x,int y,int z){
 25     e[++rp]=(SNOW){x,y,z,head[x]};head[x]=rp;
 26     e[++rp]=(SNOW){y,x,0,head[y]};head[y]=rp;
 27 }
 28 inline void ADD(int x,int y){e[++rp]=(SNOW){x,y,0,head[x]};head[x]=rp;}
 29 
 30 namespace Flow{   
 31     int S,T,dis[NN],HD[NN],q[NN],h,t,maxnflow;
 32     inline bool bfs(){
 33         memset(dis,0x3f,sizeof(dis));
 34         memcpy(head,HD,sizeof(head));
 35         q[h=t=1]=S; dis[S]=0;
 36         while(h<=t){
 37             int x=q[h++];
 38             for(int i=head[x];i;i=e[i].next) if(e[i].val)
 39                 if(dis[e[i].to]>dis[x]+1)
 40                     dis[e[i].to]=dis[x]+1,q[++t]=e[i].to;
 41             if(x==T) return 1;
 42         }return 0;
 43     }
 44     inline int dfs(int x,int in){
 45         if(x==T) return in;
 46         int rest=in,go;
 47         for(int i=head[x];i;head[x]=i=e[i].next) if(e[i].val){
 48             int y=e[i].to,v=e[i].val;
 49             if(dis[y]==dis[x]+1){
 50                 go=dfs(y,min(rest,v));
 51                 if(go) e[i].val-=go, e[i^1].val+=go, rest-=go;
 52                 else dis[y]=0;
 53             }if(!rest) break;
 54         }return in-rest;
 55     }
 56     inline int dinic(){
 57         int ans=0;
 58         memcpy(HD,head,sizeof(HD));
 59         while(bfs()) ans+=dfs(S,inf);
 60         return ans;
 61     }
 62 }using namespace Flow;
 63 
 64 namespace Tarjan{
 65     int dfn[NN],low[NN],shu,scc_num,stk[NN],top,col[NN],tot[NN];
 66     bool vis[NN];
 67     inline void tarjan(int i){
 68         low[i]=dfn[i]=++shu;
 69         stk[++top]=i,vis[i]=true;
 70         for(int k=head[i];k;k=e[k].next){
 71             int j=e[k].to;
 72             if(!dfn[j]) {
 73                 tarjan(j);
 74                 low[i]=min(low[j],low[i]);
 75             } else if(vis[j]) low[i]=min(dfn[j],low[i]);
 76         }
 77         int k;
 78         if(low[i]==dfn[i]){
 79             scc_num++;
 80             do{
 81                 k=stk[top--];
 82                 col[k]=scc_num;
 83                 tot[scc_num]++;
 84                 vis[k]=false;
 85             }while(k!=i);
 86         }
 87     }
 88 }using namespace Tarjan;
 89 
 90 int tmp,num,cnt;
 91 int pre[NN];
 92 bool inq[NN],bin[NN];
 93 unordered_map<int,int> g[NN<<1];
 94 namespace WSN{
 95     inline short main(){
 96         freopen("night.in","r",stdin);
 97         freopen("night.out","w",stdout);
 98         n=read(); m=read(); TT=read();
 99         int Tot=n+m; S=++Tot; T=S+1;
100         for(int i=1;i<=TT;i++) p[i].u=read(),p[i].v=read()+n;
101         for(int i=1;i<=n;i++) add(S,i,1);
102         for(int i=1;i<=m;i++) add(i+n,T,1);
103         for(int i=1;i<=TT;i++) add(p[i].u,p[i].v,1);
104         maxnflow=dinic();
105         // for(int i=1;i<=rp;i++) e[i].print();
106         // cout<<maxnflow<<endl;
107         for(int i=2*(n+m)+2;i<=rp;i+=2)
108             if(!e[i].val) match[++num]=(bian){e[i].fr,e[i].to,(i-2*(n+m))/2},inq[e[i].fr]=inq[e[i].to]=1,g[e[i].fr][e[i].to]=1;
109             else disma[++cnt]=(bian){e[i].fr,e[i].to,(i-2*(n+m))/2};
110         // for(int i=1;i<=num;i++) cout<<match[i].u<<" "<<match[i].v<<endl;cout<<endl;
111         memset(head,0,sizeof(head)); rp=1;
112         for(int i=1;i<=num;i++) ADD(match[i].v,match[i].u),++tmp,pre[tmp]=match[i].id;
113         for(int i=1;i<=cnt;i++) ADD(disma[i].u,disma[i].v);
114         for(int i=1;i<=n+m;i++){
115             if(inq[i]){
116                 if(i<=n) ADD(i,S);
117                 else ADD(T,i);
118             }else{
119                 if(i<=n) ADD(S,i);
120                 else ADD(i,T);
121             }
122         }
123         // for(int i=1;i<=rp;i++) e[i].print();
124         for(int i=1;i<=n+m+2;i++) if(!dfn[i]) tarjan(i);
125         // for(int i=1;i<=n+m+2;i++) cout<<col[i]<<endl;
126         for(int i=1;i<=TT;i++)
127             if(col[p[i].u]==col[p[i].v]&&!g[p[i].u][p[i].v]) ++tmp,pre[tmp]=i;
128         int ans=TT-tmp;
129         write(ans);
130         if(!ans) return puts(""),0;
131         for(int i=1;i<=tmp;i++) bin[pre[i]]=1;
132         for(int i=1;i<=TT;i++) if(!bin[i]) write(i,' ');
133         puts("");
134         return 0;
135     }
136 }
137 signed main(){return WSN::main();}
View Code

 

posted @ 2021-09-23 19:24  雪域亡魂  阅读(69)  评论(0编辑  收藏  举报