A. 手机的生产
题目链接
思路
找规律可以发现,只有$表达式的话,fork()会产生3台手机,fork()$fork()会产生4台手机,fork()$fork()$fork会产生5台手机……依次类推。
那么我们可以用|把若干个连续的$块分割开,每个长度为
x
的$块会产生
f[i]=(num[i]−1)f[i+1]+1,num[i]=第i段连续的$的长度
代码
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <algorithm>
#define MAXN 410000
#define MOD 998244353
using namespace std;
typedef long long int LL;
LL total=0;
int ans[MAXN],n;
char s[MAXN],op[MAXN];
char ch[10];
LL stack[MAXN];
int top=0;
LL f[MAXN];
int main()
{
scanf("%d",&n);
if(n==1)
{
cout<<2<<endl;
return 0;
}
for(int j=1;j<n;j++)
{
scanf("%s",ch);
if(ch[0]=='&')
op[j]='&';
else op[j]='|';
}
int h=1,t=1;
LL tmp=2;
while(h<n&&t<n)
{
if(op[t]=='&') tmp++,t++;
else
{
h=t=t+1;
stack[++top]=tmp;
tmp=2;
}
}
stack[++top]=tmp;
f[top]=stack[top];
for(int i=top-1;i>=1;i--)
f[i]=(f[i+1]*(stack[i]-1)%MOD+1)%MOD;
printf("%lld\n",f[1]);
return 0;
}
C. 谣言的传播
题目链接
思路
蒟蒻太弱,只会做40分的。。。。
前10分可以通过爆枚序列
b
的全排列得到。
之后30分可以枚举
代码
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <algorithm>
#define INF 0x3f3f3f3f
using namespace std;
int n,a[1000];
namespace bruteforce
{
const int MAXN=60;
int b[MAXN],ansmin[MAXN],ansmax[MAXN],minans=INF,maxans=-INF;
bool used[MAXN];
int sum=0;
bool vis[MAXN];
void calc(int S,int x,int fa)
{
sum++;
if(b[S]==x) return;
if(!vis[a[x]])
{
vis[a[x]]=true;
calc(S,a[x],x);
}
}
void DFS(int pos)
{
if(pos>n)
{
sum=0;
bool flag=true;
/*if(b[1]==4&&b[2]==1&&b[3]==5&&b[4]==3&&b[5]==2)
cout<<1<<endl;*/
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++) vis[j]=false;
//sum++;
vis[i]=true;
calc(i,i,0);
}
if(!flag) return;
if(sum<minans)
{
minans=sum;
for(int i=1;i<=n;i++)
ansmin[i]=b[i];
}
if(sum>maxans)
{
maxans=sum;
for(int i=1;i<=n;i++)
ansmax[i]=b[i];
}
return;
}
for(int i=1;i<=n;i++)
if(!used[i]&&i!=pos)
{
used[i]=true;
b[pos]=i;
DFS(pos+1);
used[i]=false;
}
}
void solve()
{
DFS(1);
printf("%d\n",minans);
for(int i=1;i<=n;i++)
printf("%d ",ansmin[i]);
printf("\n");
printf("%d\n",maxans);
for(int i=1;i<=n;i++)
printf("%d ",ansmax[i]);
printf("\n");
}
}
namespace KM
{
const int MAXV=1000;
const int MAXE=200000;
int S=MAXV-2,T=MAXV-1;
struct edge
{
int u,v,w,cap,next;
}edges[MAXE*2];
int head[MAXV],nCount=1;
void AddEdge(int U,int V,int W,int C)
{
edges[++nCount].u=U;
edges[nCount].v=V;
edges[nCount].w=W;
edges[nCount].cap=C;
edges[nCount].next=head[U];
head[U]=nCount;
}
void add(int U,int V,int W,int C)
{
AddEdge(U,V,W,C);
AddEdge(V,U,-W,0);
}
int q[MAXE*2],dist[MAXV],pre[MAXV];
bool inQueue[MAXV];
bool SPFA_max()
{
memset(pre,-1,sizeof(pre));
memset(dist,-INF,sizeof(dist));
memset(inQueue,false,sizeof(inQueue));
int h=0,t=1;
q[h]=S;
dist[S]=0;
inQueue[S]=true;
while(h<t)
{
int u=q[h++];
inQueue[u]=false;
for(int p=head[u];p!=-1;p=edges[p].next)
{
int v=edges[p].v;
if(dist[u]+edges[p].w>dist[v]&&edges[p].cap)
{
dist[v]=dist[u]+edges[p].w;
pre[v]=p;
if(!inQueue[v])
{
inQueue[v]=true;
q[t++]=v;
}
}
}
}
return pre[T]!=-1;
}
int MCMF_max()
{
int cost=0;
while(SPFA_max())
{
int flow=INF;
for(int p=pre[T];p!=-1;p=pre[edges[p].u])
flow=min(flow,edges[p].cap);
for(int p=pre[T];p!=-1;p=pre[edges[p].u])
{
edges[p].cap-=flow;
edges[p^1].cap+=flow;
}
cost+=flow*dist[T];
}
return cost;
}
bool SPFA_min()
{
memset(pre,-1,sizeof(pre));
memset(dist,INF,sizeof(dist));
memset(inQueue,false,sizeof(inQueue));
int h=0,t=1;
q[h]=S;
dist[S]=0;
inQueue[S]=true;
while(h<t)
{
int u=q[h++];
inQueue[u]=false;
for(int p=head[u];p!=-1;p=edges[p].next)
{
int v=edges[p].v;
if(dist[u]+edges[p].w<dist[v]&&edges[p].cap)
{
dist[v]=dist[u]+edges[p].w;
pre[v]=p;
if(!inQueue[v])
{
inQueue[v]=true;
q[t++]=v;
}
}
}
}
return pre[T]!=-1;
}
int MCMF_min()
{
int cost=0;
while(SPFA_min())
{
int flow=INF;
for(int p=pre[T];p!=-1;p=pre[edges[p].u])
flow=min(flow,edges[p].cap);
for(int p=pre[T];p!=-1;p=pre[edges[p].u])
{
edges[p].cap-=flow;
edges[p^1].cap+=flow;
}
cost+=flow*dist[T];
}
return cost;
}
bool vis[MAXV];
int b[MAXV];
int sum=0;
void calc(int S,int x,int fa)
{
sum++;
if(b[S]==x) return;
if(!vis[a[x]])
{
vis[a[x]]=true;
calc(S,a[x],x);
}
}
void solve_min()
{
memset(head,-1,sizeof(head));
nCount=1;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++) //让j作为b[i]
{
if(i==j) continue;
for(int k=1;k<=n;k++)
vis[k]=false;
b[i]=j;
sum=0;
vis[i]=true;
calc(i,i,0);
add(i,j+n,sum,1);
}
for(int i=1;i<=n;i++)
add(S,i,0,1),add(i+n,T,0,1);
int ans=MCMF_min();
for(int i=2;i<=nCount-4*n;i+=2)
if(!edges[i].cap)
b[edges[i].u]=edges[i].v-n;
printf("%d\n",ans);
for(int i=1;i<=n;i++) printf("%d ",b[i]);
printf("\n");
}
void solve_max()
{
memset(head,-1,sizeof(head));
nCount=1;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++) //让j作为b[i]
{
if(i==j) continue;
for(int k=1;k<=n;k++)
vis[k]=false;
b[i]=j;
sum=0;
vis[i]=true;
calc(i,i,0);
add(i,j+n,sum,1);
}
for(int i=1;i<=n;i++)
add(S,i,0,1),add(i+n,T,0,1);
int ans=MCMF_max();
for(int i=2;i<=nCount-4*n;i+=2)
if(!edges[i].cap)
b[edges[i].u]=edges[i].v-n;
printf("%d\n",ans);
for(int i=1;i<=n;i++) printf("%d ",b[i]);
printf("\n");
}
void solve()
{
solve_min();
solve_max();
}
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
if(n<=8)
{
using namespace bruteforce;
solve();
}
else
{
using namespace KM;
solve();
}
return 0;
}