zoukankan      html  css  js  c++  java
  • noi.ac NOI挑战营模拟赛1-5

    注:因为博主是个每次考试都爆零垫底的菜鸡,所以此篇博客很有可能咕咕咕

    (指只贴AC代码不写题解的......如果我真的不会做的话,就不能怪我了qwqwq)


    Day1

    T1 swap

    • 23pts 从一个状态开始爆搜,然后我们哈希一下状态,保证一个状态只被访问一次。时间复杂度(O(n!n)),感觉复杂度过55分没问题,但是到后面会RE.......不知为何呀QAQ
    • 55pts 枚举一下这个之后的排列,然后我们再通过判断一下每两个宽度大于n的人没有没更换相对位置来判断该结束状态的合法性(相对位置指如果原先pos_x<pos_y,之后pos_x仍然小于pos_y)。
    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    #include<cstring>
    #define MAXN 100010
    using namespace std;
    int n,m,tot,ans;
    int a[MAXN],pos[MAXN];
    struct Line{int u,v;}line[MAXN<<1];
    inline bool check()
    {
    	for(int i=1;i<=tot;i++)
    		if(pos[line[i].u]>pos[line[i].v]) return false;
    	return true;
    }
    int main()
    {
    	#ifndef ONLINE_JUDGE
    	freopen("ce.in","r",stdin);
    	#endif
    	scanf("%d%d",&n,&m);
    	for(int i=1;i<=n;i++) scanf("%d",&a[i]);
    	for(int i=1;i<=n;i++)
    		for(int j=i+1;j<=n;j++)
    			if(a[i]+a[j]>m)
    				line[++tot]=(Line){i,j};
    	for(int i=1;i<=n;i++) pos[i]=i;
    	do{
    		if(check()==true) ans++;
    	}while(next_permutation(&pos[1],&pos[n+1]));
    	printf("%d
    ",ans);
    	return 0;
    }
    

    满分做法比较神仙,就是我们从小到大处理。对于当前最小的数,我们判断它和当前最大的数能不能交换;
    如果它和最大的可以交换,那么它和当前数列里面的所有数都可以交换(意思是最后的位置有 当前序列中数的数量-->n 种)所以我们可以给答案乘上n,然后去掉这个最小数,对于剩下的序列递归计算(因为最后无论这个子序列是什么情况,最小数都可以以n种方式插入到它们中间构成答案);
    如果它不能和最大的交换,那么最大的就无法和当前序列中任意一个数交换,所以它就没用了,只有在它当前位置上那一种贡献,我们删去它,递归处理子序列即可。

    • 100pts
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<vector>
    #include<cmath>
    #include<algorithm>
    #define MAXN 100010
    #define mod 1000000007
    using namespace std;
    int n,m;
    int a[MAXN];
    vector<int>vec;
    inline int solve(vector<int>x)
    {
    //	for(int i=0;i<x.size();i++) printf("%d ",x[i]); puts("");
    	if(x.size()<=1) return 1;
    	int min_pos,max_pos,minn=0x3f3f3f3f,maxx=-0x3f3f3f3f;
    	for(int i=0;i<x.size();i++) 
    		if(x[i]<minn)
    			minn=x[i],min_pos=i;
    	for(int i=0;i<x.size();i++)
    		if(x[i]>maxx)
    			maxx=x[i],max_pos=i;
    //	printf("max_pos=%d min_pos=%d
    ",max_pos,min_pos);
    	if(x[min_pos]+x[max_pos]>m)
    	{
    		vector<int>cur1,cur2;
    		cur1.clear(),cur2.clear();
    		for(int i=0;i<max_pos;i++) cur1.push_back(x[i]);
    		for(int i=max_pos+1;i<x.size();i++) cur2.push_back(x[i]);
    		int cur_ans1=solve(cur1);
    		int cur_ans2=solve(cur2);
    		return 1ll*cur_ans1*cur_ans2%mod;
    	}
    	vector<int>cur;
    	cur.clear();
    	for(int i=0;i<min_pos;i++) cur.push_back(x[i]);
    	for(int i=min_pos+1;i<x.size();i++) cur.push_back(x[i]);
    	return 1ll*solve(cur)*x.size()%mod;
    }
    int main()
    {
    	#ifndef ONLINE_JUDGE
    	freopen("ce.in","r",stdin);
    	#endif
    	scanf("%d%d",&n,&m);
    	for(int i=0;i<n;i++) scanf("%d",&a[i]),vec.push_back(a[i]);
    	if(n==1) {printf("1
    ");return 0;}
    	printf("%d
    ",solve(vec));
    	return 0;
    }
    
    

    T2 stat

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #define MAXN 75
    #define mod 1000000007
    using namespace std;
    int n,k;
    int a[MAXN],b[MAXN];
    inline void print(int *x)
    {
    	for(int i=1;i<=n;i++) printf("%d ",x[i]);
    	puts("");
    }
    
    namespace subtask1
    {
    	inline void solve()
    	{
    		int ans=0;
    		for(int i=1;i<=n;i++) a[i]=b[i]=i;
    		do
    		{
    			do
    			{
    				int cur_ans=0;
    				for(int i=1;i<=n;i++) cur_ans+=max(a[i],b[i]);
    				if(cur_ans>=k) ans++;
    			}while(next_permutation(&b[1],&b[n+1]));
    		}while(next_permutation(&a[1],&a[n+1]));
    		printf("%d
    ",ans);
    	}
    }
    
    namespace subtask2
    {
    	long long ans=0;
    	int tmp[MAXN],done[MAXN];
    	inline void search(int x)
    	{
    		if(x>n)
    		{
    			long long sum=0;
    			for(int i=1;i<=n;i++) sum+=max(tmp[i],i);
    			if(sum>=k) ans++;
    			return; 
    		}	
    		for(int i=1;i<=n;i++)
    		{
    			if(done[i]) continue;
    			tmp[x]=i,done[i]=1;
    			search(x+1);
    			tmp[x]=0,done[i]=0;
    		}
    	}
    	inline void solve()
    	{
    		for(int i=1;i<=n;i++) done[i]=0;
    		search(1);
    		for(int i=1;i<=n;i++)
    			ans=1ll*ans*i%mod;
    		printf("%lld
    ",ans);
    	}
    }
    
    namespace subtask3
    {
    	long long ans;
    	long long f[80][80][5010];
    	inline void solve()
    	{
    		f[0][0][0]=1;
    		for(int i=1;i<=n;++i)
    			for(int j=0;j<i;++j)
    				for(int k=0;k<=4901;++k)
    					if(f[i-1][j][k])
    					{
    						f[i][j+1][k+i]=(f[i][j+1][k+i]+f[i-1][j][k])%mod;
    						f[i][j+2][k+2*i]=(f[i][j+2][k+2*i]+f[i-1][j][k]*(i-1-j)*(i-1-j))%mod;
    						f[i][j+1][k+i]=(f[i][j+1][k+i]+2*f[i-1][j][k]*(i-1-j))%mod;
    						f[i][j][k]=(f[i][j][k]+f[i-1][j][k])%mod;
    					}
    		for(int i=k;i<=4901;++i)
    			ans=(ans+f[n][n][i])%mod;
    		for(int i=1;i<=n;++i)
    			ans=(ans*i)%mod;
    		printf("%lld",ans);
    	}
    }
    
    using namespace subtask1;
    using namespace subtask2;
    using namespace subtask3;
    
    int main()
    {
    	#ifndef ONLINE_JUDGE
    	freopen("ce2.in","r",stdin);
    	#endif
    	scanf("%d%d",&n,&k);
    	if(n<=5) subtask1::solve();
    	else if(n<=10) subtask2::solve();
    	else subtask3::solve();
    	return 0;
    }
    
    

    T3 sequence


    Day2

    T1 baby

    #include<algorithm>
    #include<cstdio>
    #include<cstring>
    #define N 550000
    #define M 100005
    using namespace std;
    int a[N][4],b[5]={-1,0,1,0,-1},d[M],e[M],f[M],g[M],h[M],i,j,l,m,n,o[N<<2],p[N<<2],q,s[N<<3],t,z;char c[N];bool w[N][4];
    inline void add(int u){while(u<=t<<1)s[u]++,u+=u&-u;}
    inline void del(int u){while(u<=t<<1)s[u]--,u+=u&-u;}
    inline bool cmp(int u,int v){return a[d[u]][f[u]]<a[d[v]][f[v]];}
    void dfs(int u,int v)
    {
    	++v%=4;
    	while(!w[u][v])(v+=3)%=4;
    	if(a[u][v]<=t)return;
    	a[u][v]=++t,o[t]=u,p[t]=v;
    	dfs(u+m*b[v]+b[v+1],v);
    }
    inline int sum(int u)
    {
    	int v=0;
    	while(u)v+=s[u],u-=u&-u;
    	return v;
    }
    int main()
    {
    	#ifndef ONLINE_JUDGE
    	freopen("ce.in","r",stdin);
    	#endif
    	scanf("%d%d%d%*s",&n,&m,&q),memset(a,0x7f,sizeof a);
    	for(i=1;i<=n;i++)
    	{
    		for(scanf("%s",c),j=1;j<m;j++)if(c[j<<1]=='.')w[(i-1)*m+j][1]=w[(i-1)*m+j+1][3]=true;
    		for(scanf("%s",c+1),j=1;j<=m;j++)if(c[j<<1]=='.')w[(i-1)*m+j][2]=w[i*m+j][0]=true;
    	}
    	for(i=0;i<q;i++)
    	{
    		int x,y;
    		scanf("%d%d",&x,&y),d[i]=(x-1)*m+y;
    		scanf("%d%d",&x,&y),e[i]=(x-1)*m+y;
    		scanf("%s",c),g[i]=i;
    		if(*c=='U')f[i]=0;
    		else if(*c=='R')f[i]=1;
    		else if(*c=='D')f[i]=2;
    		else if(*c=='L')f[i]=3;
    		while(!w[d[i]][f[i]])(f[i]+=3)%=4;
    	}
    	for(dfs(1,0),i=1;i<=n*m;i++)add(min(min(a[i][0],a[i][1]),min(a[i][2],a[i][3])));
    	for(sort(g,g+q,cmp),i=1,j=0;j<q;)
    	{
    		while(i<=t&&a[d[g[j]]][f[g[j]]]>i)
    		del(i),a[o[i]][p[i]]+=t,add(min(min(a[o[i]][0],a[o[i]][1]),min(a[o[i]][2],a[o[i]][3]))),i++;
    		while(j<q&&a[d[g[j]]][f[g[j]]]==i)
    		h[g[j]]=sum(min(min(a[e[g[j]]][0],a[e[g[j]]][1]),min(a[e[g[j]]][2],a[e[g[j]]][3]))),j++;
    	}
    	for(i=0;i<q;i++)printf("%d
    ",h[i]);
    	return 0;
    }
    

    T2 Bike

    T3 Boom


    Day3

    T1 sequence

    神仙乱搞qwq

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #include<vector>
    #define MAXN 100010
    using namespace std;
    int n,m,q,tot,K,base,mod;
    int a[MAXN],rt[MAXN];
    bool done[MAXN];
    struct Node{int v,ls,rs;}t[MAXN<<5];
    struct Node2{int r_pos,hash;};
    vector<int>pos[MAXN];//pos[a]表示a值的位置
    inline void insert(int &x,int f,int l,int r,int k)
    {
        x=++tot;
        t[x]=t[f],t[x].v++;
        if(l==r) return;
        int mid=(l+r)>>1;
        if(k<=mid) insert(t[x].ls,t[f].ls,l,mid,k);
        else insert(t[x].rs,t[f].rs,mid+1,r,k);
    }
    inline int query(int x,int l,int r,int k)
    {
        if(k>t[x].v||k==0) return -1;
        if(l==r) return l;
        int mid=(l+r)>>1;
        if(k<=t[t[x].ls].v) return query(t[x].ls,l,mid,k);
        else return query(t[x].rs,mid+1,r,k-t[t[x].ls].v);
    }
    inline void solve(vector<Node2>&x)
    {
        for(int now=1;now<=n;now++)
        {
            vector<Node2>nxt;
            int minn=query(rt[x[0].r_pos+1],1,MAXN-10,now);
            // cout<<"minn="<<minn<<endl;
            if(minn==-1) return;
            int st=0;
            for(st=pos[minn].size()-1;st>=0;st--)
                {if(pos[minn][st]<=x[0].r_pos) break;}
            // cout<<"st="<<st<<endl;
            if(st+1==(int)pos[minn].size()) continue;
            for(int i=st+1;i<pos[minn].size();i++)//枚举之后能接哪些位置
            {
                for(int j=0;j<x.size()&&x[j].r_pos<pos[minn][i];j++)//枚举前面从哪个位置来接新数
                {
                    int hash=(1ll*x[j].hash*base+minn)%mod;
                    printf("%d
    ",hash);
                    // printf("K=%d
    ",K);
                    K--;
                    if(K<=0) return;
                    nxt.push_back((Node2){pos[minn][i],hash});
                }
                if(K<=0) return;
            }
            // for(int i=0;i<nxt.size();i++) cout<<nxt[i].r_pos<<" "; cout<<endl;
            solve(nxt);
            if(K<=0) return;
        }
    }
    int main()
    {
        #ifndef ONLINE_JUDGE
        freopen("ce.in","r",stdin);
        #endif
        scanf("%d%d%d%d",&n,&K,&base,&mod);
        for(int i=1;i<=n;i++) scanf("%d",&a[i]),pos[a[i]].push_back(i);
        for(int i=n;i>=0;i--) 
        {
            if(done[a[i]]==0) 
                done[a[i]]=1,insert(rt[i],rt[i+1],1,MAXN-10,a[i]);
            else rt[i]=rt[i+1];
        }
        // for(int i=1;i<=n;i++) printf("rt[%d]=%d
    ",i,rt[i]); 
        vector<Node2>cur;
        cur.push_back((Node2){0,0});
        solve(cur);
        return 0;
    }
    
    

    T2 game

    这份代码是用emacs写的......所以缩进锅了qwqwq

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<algorithm>
    #include<cstring>
    #include<vector>
    #define MAXN 300010
    #define mod 1000000007
    using namespace std;
    int n,A,B,ans1,ans2,t;
    int ans[MAXN],ffa[MAXN],b[MAXN],g[MAXN],c[MAXN];
    int head[MAXN],dis[MAXN],fa[MAXN],pref[MAXN],suf[MAXN];
    struct Edge{int nxt,to;}edge[MAXN<<1];
    inline bool cmp(int x,int y){return ans[x]>ans[y];}
    inline void add(int from,int to)
    {
        edge[++t].nxt=head[from],edge[t].to=to;
        head[from]=t;
    }
    inline void dfs1(int x,int pre,int ban)
    {
        ans[x]=0;
        for(int i=head[x];i;i=edge[i].nxt)
        {
    	int v=edge[i].to;
    	if(v==pre||v==ban) continue;
    	dfs1(v,x,ban);
        }
        int cur=0;
        for(int i=head[x];i;i=edge[i].nxt)
        {
    	int v=edge[i].to;
    	if(v==pre||v==ban) continue;
    	b[++cur]=v;
        }
        sort(&b[1],&b[cur+1],cmp);
        for(int i=1;i<=cur;i++) ans[x]=max(ans[x],ans[b[i]]+i);
    }
    inline void dfs2(int x,int pre)
    {
        int t=0;
        if(pre) ans[0]=g[x],b[++t]=0;
        for(int i=head[x];i;i=edge[i].nxt)
        {
    	int v=edge[i].to;
    	if(v==pre) continue;
    	b[++t]=v;
        }
        sort(&b[1],&b[t+1],cmp);
        pref[0]=suf[t+1]=0;
        for(int i=1;i<=t;i++) pref[i]=max(pref[i-1],ans[b[i]]+i);
        ans1=min(ans1,pref[t]);
        for(int i=t;i;i--) suf[i]=max(suf[i+1],ans[b[i]]+i-1);
        for(int i=1;i<=t;i++)
    	if(b[i])
    	    g[b[i]]=max(pref[i-1],suf[i+1]);
        for(int i=head[x];i;i=edge[i].nxt)
        {
    	int v=edge[i].to;
    	if(v!=pre)
    	    dfs2(v,x);
        }
    }
    inline void dfs3(int x,int pre)
    {
        for(int i=head[x];i;i=edge[i].nxt)
        {
    	int v=edge[i].to;
    	if(v==pre) continue;
    	ffa[v]=x;
    	dfs3(v,x);
        }
    }
    int main()
    {
        #ifndef ONLINE_JUDGE
        freopen("ce.in","r",stdin);
        #endif
        scanf("%d%d%d",&n,&A,&B);
        for(int i=1;i<n;i++)
        {
    	int x,y;
    	scanf("%d%d",&x,&y);
    	add(x,y),add(y,x);
        }
        dfs1(1,0,0);
        ans1=n-1;
        dfs2(1,0);
        printf("%d
    ",ans1);
        
        dfs3(A,0);
        int now=B,top=0;
        while(now) c[++top]=now,now=ffa[now];
        int l=1,r=top-1;
        ans2=n-1;
        while(l<=r)
        {
    	int mid=(l+r)>>1;
    	dfs1(A,0,c[mid]);
    	dfs1(B,0,c[mid+1]);
    	ans2=min(ans2,max(ans[A],ans[B]));
    	if(ans[A]>ans[B]) l=mid+1;
    	else r=mid-1;
        }
        printf("%d
    ",ans2);
        return 0;
    }
    
    
    

    T3 tree

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #define MAXN 100010
    #define mod 1000000007
    using namespace std;
    int n,m;
    int f[MAXN][11],fa[MAXN],st[MAXN];
    inline int fpow(int x,int y)
    {
        int cur_ans=1;
        while(y)
        {
            if(y&1) cur_ans=1ll*cur_ans*x%mod;
            x=1ll*x*x%mod;
            y>>=1;
        }
        return cur_ans;
    }
    inline void dp(int x,int y)
    {
        for(int i=10;i;i--)
            for(int j=1;j<i;j++)
                f[x][i]=(f[x][i]+1ll*f[x][j]*f[y][i-j]%mod)%mod;
    }
    inline void dp2(int x,int y)
    {
        for(int i=1;i<=10;i++)
            for(int j=1;j<i;j++)
                f[x][i]=(f[x][i]-1ll*f[x][j]*f[y][i-j]%mod)%mod;
    }
    int main()
    {
        #ifndef ONLINE_JUDGE
        freopen("ce.in","r",stdin);
        freopen("ce.out","w",stdout);
        #endif
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++) scanf("%d",&f[i][1]);
        for(int i=2;i<=n;i++) scanf("%d",&fa[i]);
        for(int i=n;i>1;i--) dp(fa[i],i);
        for(int p=1;p<=m;p++)
        {
            int op,k,s,t,top;
            scanf("%d%d%d",&op,&k,&s);
            if(op==1)
            {
                for(int i=1;i<=10;i++) f[0][i]=0;
                for(t=k,top=0;t&&top<10;t=fa[t]) st[++top]=t;
                while(t=st[top--])
                {
                    for(int i=1;i<=10;i++) 
                        f[n+1][i]=f[0][i],f[0][i]=f[t][i];
                    dp(0,n+1);
                    if(top) dp2(0,st[top]);
                }
                printf("%d
    ",(f[0][s]+mod)%mod);
            }
            else
            {
                for(t=k,top=0;t&&top<10;t=fa[t]) st[++top]=t;
                for(int i=top-1;i;i--) dp2(st[i+1],st[i]);
                int cur_ans=1ll*fpow(f[k][1],mod-2)*s%mod;
                for(int i=1;i<=10;i++) 
                    f[k][i]=1ll*f[k][i]*cur_ans%mod;
                for(int i=1;i<top;i++)
                    dp(st[i+1],st[i]);
            }
        }
        return 0;
    }
    
    

    Day4

    T1 tree

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #define MAXN 3010
    using namespace std;
    int n,q,k,t,ans=0x3f3f3f3f;
    int dp[MAXN][MAXN][3],siz[MAXN],head[MAXN];
    struct Edge{int nxt,to,dis;}edge[MAXN<<1];
    inline void add(int from,int to,int dis)
    {
    	edge[++t].nxt=head[from],edge[t].to=to,edge[t].dis=dis;
    	head[from]=t;
    }
    inline void solve(int x,int pre)
    {
    	siz[x]=1;
    	dp[x][1][0]=dp[x][1][1]=dp[x][1][2]=0;
    	dp[x][0][0]=dp[x][0][1]=dp[x][0][2]=0;
    	for(int i=head[x];i;i=edge[i].nxt)
    	{
    		int v=edge[i].to;
    		if(v==pre) continue;
    		solve(v,x);
    //		printf("x=%d v=%d
    ",siz[x],siz[v]);
    		for(int j=min(k,siz[x]+siz[v]);j>=2;j--)
    		{
    			for(int j2=max(1,j-siz[x]);j2<=min(j,siz[v]);j2++)//v_size
    			{
    				int j1=j-j2;//x_size
    //				cout<<j2<<" "<<j2<<endl;
    				dp[x][j][0]=min(dp[x][j][0],dp[x][j1][0]+dp[v][j2][0]+edge[i].dis*2);
    				dp[x][j][1]=min(dp[x][j][1],dp[x][j1][0]+dp[v][j2][1]+edge[i].dis);
    				dp[x][j][1]=min(dp[x][j][1],dp[x][j1][1]+dp[v][j2][0]+edge[i].dis*2);
    				dp[x][j][2]=min(dp[x][j][2],dp[x][j1][1]+dp[v][j2][1]+edge[i].dis);
    				dp[x][j][2]=min(dp[x][j][2],dp[x][j1][2]+dp[v][j2][0]+edge[i].dis*2);
    				dp[x][j][2]=min(dp[x][j][2],dp[x][j1][0]+dp[v][j2][2]+edge[i].dis*2);
    			}
    		}
    		siz[x]+=siz[v];
    	}
    	ans=min(ans,dp[x][k][2]);
    //	printf("x=%d %d
    ",x,ans);
    }
    int main()
    {
    	#ifndef ONLINE_JUDGE
    	freopen("ce.in","r",stdin);
    	#endif
    	scanf("%d%d",&n,&k);
    	for(int i=1;i<n;i++)
    	{
    		int u,v,w;
    		scanf("%d%d%d",&u,&v,&w);
    		add(u,v,w),add(v,u,w);
    	}
    	memset(dp,0x3f,sizeof(dp));
    	solve(1,0);
    	printf("%d
    ",ans);
    	return 0;
    }
    
    

    T2

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #define MAXN 10000000
    #define mod 998244353
    using namespace std;
    int n,k,T;
    int inv[MAXN+10],ff[MAXN+10],fn[MAXN+10],F[MAXN+10];
    inline int fpow(int x,int y)
    {
        int cur_ans=1;
        while(y)
        {
            if(y&1) cur_ans=1ll*cur_ans*x%mod;
            x=1ll*x*x%mod;
            y>>=1;
        }
        return cur_ans;
    }
    int main()
    {
        #ifndef ONLINE_JUDGE
        freopen("ce.in","r",stdin);
        #endif
        scanf("%d%d%d",&n,&k,&T);
        if(T==1) 
        {
            printf("1
    ");
            return 0;
        }
        fn[0]=1;
        for(int i=1;i<=MAXN;i++) fn[i]=1ll*fn[i-1]*i%mod;
        inv[MAXN]=fpow(fn[MAXN],mod-2);
        for(int i=MAXN-1;i>=0;i--) inv[i]=1ll*inv[i+1]*(i+1)%mod;
        for(int i=1;i<=MAXN;i++) ff[i]=1ll*inv[i]*fn[i-1]%mod;
        int cur_ans=1;
        int cur=fpow(T-1,mod-2);
        F[0]=1ll*T*(mod-cur)%mod*(1-fpow(T,n)+mod)%mod;
        for(int i=1;i<=k;i++)
        {
            cur_ans=1ll*cur_ans*(n-i+1)%mod*ff[i]%mod;
            F[i]=(1ll*F[i-1]-1ll*T*cur_ans%mod+mod)%mod;
            F[i]=1ll*F[i]*cur%mod;
        }
        cur_ans=fpow(cur_ans,mod-2);
        printf("%lld
    ",1ll*cur_ans*F[k-1]%mod);
        return 0;
    }
    
    

    T3

    这个题的快读板子感觉挺好qwqwq

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<vector>
    #include<algorithm>
    #define MAXN 1000010
    using namespace std;
    namespace io {
    	const int SIZE = (1 << 21) + 1;
    	char ibuf[SIZE], *iS, *iT, obuf[SIZE], *oS = obuf, *oT = oS + SIZE - 1, c, qu[55]; int qr;
    	// getchar
    	#define gc() (iS == iT ? (iT = (iS = ibuf) + fread (ibuf, 1, SIZE, stdin), (iS == iT ? EOF : *iS ++)) : *iS ++)
    	// print the remaining part
    	inline void flush () {
    		fwrite (obuf, 1, oS - obuf, stdout);
    		oS = obuf;
    	}
    	// putchar
    	inline void putc (char x) {
    		*oS ++ = x;
    		if (oS == oT) flush ();
    	}
    	// input a integer
    	template <class I>
    	inline void gi (I &x) {
    		for (c = gc(); c < '0' || c > '9'; c = gc());
    		for (x = 0; c <= '9' && c >= '0'; c = gc()) x = x * 10 + (c & 15);
    	}
    	// print a integer
    	template <class I>
    	inline void print (I &x) {
    		if (!x) putc ('0');
    		while (x) qu[++ qr] = x % 10 + '0',  x /= 10;
    		while (qr) putc (qu[qr --]);
    	}
    }
    using io :: gi;
    using io :: putc;
    using io :: print;
    int n,Q;
    int a[MAXN],p[MAXN],pos[MAXN],ans[MAXN],head[MAXN];
    struct Node{int l,d,id,nxt;}q[MAXN];
    inline void insert(int &x,int k)
    {
        for(int i=30;i>=0;i--)
        {
            if(x&(1<<i)) 
            {
                if(!p[i]) {p[i]=x,pos[i]=k;return;}
                if(k>pos[i]) swap(k,pos[i]),swap(p[i],x);
                x^=p[i];
            }
        }
    }
    inline int query(int cur_ans,int l)
    {
        for(int i=30;i>=0;i--)
            if(l<=pos[i]&&(cur_ans^p[i])>cur_ans) 
    			cur_ans=cur_ans^p[i];
        return cur_ans;
    }
    int main()
    {
        gi(n);
        for(int i=1;i<=n;i++) gi(a[i]);
        gi(Q);
        for(int i=1;i<=Q;++i)
    	{
    		int l,r,d;
    		gi(l),gi(r),gi(d); 
    		q[i]=(Node){l,d,i,head[r]};
    		head[r]=i;
    	}
    	for(int i=1;i<=n;++i)
    	{
    		insert(a[i],i);
    //		for(int i=0;i<=10;i++) printf("p[%d]=%d
    ",i,p[i]);
    		for(int j=head[i];j;j=q[j].nxt) 
    			ans[q[j].id]=query(q[j].d,q[j].l);
    	}
    	for(int i=1;i<=Q;++i) print(ans[i]),putc('
    ');
    	io::flush();
        return 0;
    }
    
    

    Day5

    T1 tree

    T2 permutation

    有限制位置的错排问题。

    • 10pts 枚举排列,然后判断是否是对的。时间复杂度(O(n!n))
    • 100pts 我们考虑容斥。
      我们把已经看到值的位置直接忽略,之后就不放这个位置了,如果没有错排的限制,显然结果是((n-k)!)的。
      但是这样有一部分是错的对吧,错的就是比如1放到了1这种情况,我们去掉这种一个数放错的情况,就是减去(C_{m}^1(n-k-1)!)
      但是这样子就减多了,比如说1,2放到了1,2这种两个数放错的情况,所以要加上(C_{m}^2(n-k-2)!)
      .......然后以此类推,就是答案了.
      其中注意一下,如果这个数开始已经被放过了,那么我们也不需要管它.
      所以m的数量是自己原先既没有摆放位置,它对应的位置也没有数的个数.

    (考场忘了最后(ans+mod)%mod)了,炸成了40.......
    AC代码:

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<algorithm>
    #include<cstring>
    #define MAXN 1000010
    #define mod 998244353
    using namespace std;
    int n;
    int p[MAXN];
    namespace subtask1 //10pts
    {
    	int ans,cnt;
    	int done[MAXN],cur[MAXN];
    	inline void search(int x)
    	{
    		if(x>n)
    		{
    //			for(int i=1;i<=n;i++) printf("%d ",cur[i]); puts("");
    			ans++;
    			return;
    		}
    		if(p[x]){cur[++cnt]=p[x];search(x+1);cnt--;return;}
    		for(int i=1;i<=n;i++)
    		{
    			if(done[i]||i==x) continue;
    			done[i]=1;cur[++cnt]=i;
    			search(x+1);
    			done[i]=0;cnt--;
    		}
    	}
    	inline void solve()
    	{
    		for(int i=1;i<=n;i++) if(p[i]) done[p[i]]=1;
    		search(1);
    		printf("%d
    ",ans);
    	}
    }
    namespace subtask2
    {
    	int fn[MAXN],inv[MAXN],f[MAXN],done[MAXN];
    	inline int fpow(int x,int y)
    	{
    		int cur_ans=1;
    		while(y)
    		{
    			if(y&1) cur_ans=1ll*cur_ans*x%mod;
    			x=1ll*x*x%mod;
    			y>>=1;
    		}
    		return cur_ans;
    	}
    	inline void init()
    	{
    		fn[0]=1;
    		for(int i=1;i<=MAXN-10;i++) fn[i]=1ll*fn[i-1]*i%mod;
    		inv[MAXN-10]=fpow(fn[MAXN-10],mod-2);
    		for(int i=MAXN-10-1;i>=0;i--) inv[i]=1ll*inv[i+1]*(i+1)%mod;
    //		for(int i=0;i<5;i++) printf("fn[%d]=%d
    ",i,fn[i]);
    //		for(int i=0;i<5;i++) printf("inv[%d]=%d
    ",i,inv[i]);
    	}
    	inline int C(int x,int y)
    	{
    		if(y==0||x==y) return 1;
    		if(y>x) return 0;
    		return 1ll*fn[x]*inv[y]%mod*inv[x-y]%mod; 
    	}
    	inline void solve()
    	{
    		init();
    		int m=0,ans=0,g=1,k=0;
    		for(int i=1;i<=n;i++) 
    		{
    			if(p[i]) 
    				k++,done[p[i]]=1;
    		}
    		for(int i=1;i<=n;i++)
    			if(done[i]==0&&p[i]==0) m++;
    		for(int i=0;i<=m;i++)
    		{
    //			cout<<fn[n-k-1]<<" "<<C(m,i)<<endl;
    			ans=(ans+1ll*g*fn[n-k-i]%mod*C(m,i))%mod;
    			g*=-1;
    //			printf("i=%d ans=%d
    ",i,ans);
    		}
    		printf("%d
    ",(ans+mod)%mod);
    	}
    }
    using namespace subtask1;
    using namespace subtask2;
    int main()
    {
    	#ifndef ONLINE_JUDGE
    	freopen("ce.in","r",stdin);
    	#endif
    	scanf("%d",&n);
    	for(int i=1;i<=n;i++) scanf("%d",&p[i]);
    	if(n<=10) subtask1::solve();
    	else subtask2::solve();
    	return 0;
    }
    
    

    T3 color

    • 20pts 暴力枚举每条边的状态,然后判断即可。时间复杂度(O(n^2 2^n))
    • 40(=20+20)pts 一条链的状态,显然每个点的答案等于(i*(n-i+1))
    • 60(=20+40)pts 我们设(dp[i])表示以i为根的子树的答案,那么我们枚举一下每个点作为根,就能算出来答案了。时间复杂度(O(n^2))
    • 100pts 我们加上换根DP即可把枚举根的那个n优化掉。(但是注意去除影响的时候不能直接除逆元,因为这道题累加答案的操作是乘法,如果乘上了一个0的逆元就GG了--->会挂成70分)时间复杂度(O(n))
      AC代码:
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #include<vector>
    #define MAXN 100010
    #define mod 1000000007
    using namespace std;
    int n,t;
    int fa[MAXN],dp[MAXN],head[MAXN];
    int up[MAXN],pref[MAXN],suf[MAXN],b[MAXN];
    struct Edge{int nxt,to;}edge[MAXN<<1];
    vector<int>e[MAXN];
    inline void add(int from,int to)
    {
    	edge[++t].nxt=head[from],edge[t].to=to;
    	head[from]=t;
    }
    inline int fpow(int x,int y)
    {
    	int cur_ans=1;
    	while(y)
    	{
    		if(y&1) cur_ans=1ll*cur_ans*x%mod;
    		x=1ll*x*x%mod;
    		y>>=1;
    	}
    	return cur_ans;
    }
    inline void init(int x,int pre)
    {
    	dp[x]=1;
    	for(int i=head[x];i;i=edge[i].nxt)
    	{
    		int v=edge[i].to;
    		if(v==pre) continue;
    		init(v,x);
    		dp[x]=1ll*dp[x]*(dp[v]+1)%mod;
    //		dp[x]=(dp[x]+1ll*dp[x]*(dp[v]+1))%mod;
    	}
    }
    inline void change_root(int x,int pre)
    {
    	dp[x]=1ll*dp[x]*(up[x]+1)%mod;
    	int cnt=0;
    	for(int i=head[x];i;i=edge[i].nxt)
    	{
    		int v=edge[i].to;
    		if(v==pre) continue;
    		b[++cnt]=dp[v];
    	}
    	pref[0]=(up[x]+1)%mod;
    	suf[cnt+1]=1;
    	for(int i=1;i<=cnt;i++) pref[i]=1ll*pref[i-1]*(b[i]+1)%mod;
    	for(int i=cnt;i>=1;i--) suf[i]=1ll*suf[i+1]*(b[i]+1)%mod;
    	cnt=0;
    	for(int i=head[x];i;i=edge[i].nxt)
    	{
    		int v=edge[i].to;
    		if(v==pre) continue;
    		cnt++;
    		up[v]=1ll*pref[cnt-1]*suf[cnt+1]%mod;
    	}
    	for(int i=head[x];i;i=edge[i].nxt)
    	{
    		int v=edge[i].to;
    		if(v==pre) continue;
    		change_root(v,x);
    	}
    }
    int main()
    {
    	#ifndef ONLINE_JUDGE
    	freopen("ce.in","r",stdin);
    	#endif
    	scanf("%d",&n);
    	for(int i=2;i<=n;i++) 
    	{
    		scanf("%d",&fa[i]);
    		add(fa[i],i),add(i,fa[i]);
    		e[fa[i]].push_back(i);
    		e[i].push_back(fa[i]);
    	}
    	init(1,0);
    //	for(int i=1;i<=n;i++) up[i]=1;
    	change_root(1,0);
    	for(int i=1;i<=n;i++) printf("%d ",dp[i]);
    	return 0;
    }
    
    
  • 相关阅读:
    NET 4.+ & .NET CORE 高性能 轻量级 ORM框架,众多.NET框架中最容易使用的数据库访问技术
    mvc cookie
    正则表达式捕获带有属性的标签
    IT第十天
    代码段
    关于java.lang中String类的学习:最特殊的数据类型(持续整理中......)
    关于String.concat()方法和StringBuffer.append()方法的学习:方法是如何追加字符到源字符串的
    关于String和StringBuffer的理解问题:指针、变量的声明、变量的值的变化
    关于字符串检索、关键词的搜索问题:已搜索过的部分不会再被纳入下次搜索的范围内
    IT第九天
  • 原文地址:https://www.cnblogs.com/fengxunling/p/10980035.html
Copyright © 2011-2022 走看看