2018.10.06 练习赛

T1 Too Young

题解:

设状态\(F[S]\),分四个阶段转移:

1.\(F[S]\)表示可以组成集合\(S\)的有多少盒子

2.\(F[S]\)表示可以组成\(S\)的子集的有多少盒子

3.\(F[S]\)表示并集为\(S\)的方案数

4.\(F[S]\)表示有多少种方式可以表示\(S\)的子集

答案即第三阶段时的\(F[\)全集\(]\)

\(code\):

#include<stdio.h>
#include<ctype.h>
using namespace std;

char buf[1<<20],*p1,*p2;
inline char gc()
{
//	return getchar();
	return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<20,stdin))==p1?0:*p1++;
}

template<typename T>
inline void read(T &x)
{
	char tt;
	while(!isdigit(tt=gc()));x=tt-'0';
	while(isdigit(tt=gc())) x=x*10+tt-'0';
}

int n,m,tot;
int f[1<<23],pow_[1<<23];
const int mod=1e9+7;

inline int add(int a,int b){return a+b<mod?a+b:a+b-mod;}
inline int sub(int a,int b){return a-b<0?a-b+mod:a-b;}

int main()
{
	read(n),read(m);
	tot=1<<m;
	for(int i=1;i<=n;i++)
	{
		int t,x,s=0;read(t);
		for(int j=1;j<=t;j++)
		read(x),s|=1<<(x-1);f[s]++;
	}
	
	for(int i=0;i<m;i++)
	for(int s=0;s<tot;s++)
	if(s>>i&1)
	f[s]=add(f[s],f[s^(1<<i)]);
	
	pow_[0]=1;
	for(int i=1;i<=(1<<22);i++) 
	pow_[i]=add(pow_[i-1],pow_[i-1]);
	for(int s=0;s<tot;s++) 
	f[s]=pow_[f[s]];
	
	for(int i=0;i<m;i++)
	for(int s=0;s<tot;s++)
	if(s>>i&1)
	f[s]=sub(f[s],f[s^(1<<i)]);
	
	printf("%d",f[tot-1]);
}

T2 Too Simple

题解:(copy出题人原话)

一个状态应该包含,每种颜色的剩余数量,以及当前画的最后一笔的颜色。

所以状态就是\(f[k][(i_1...,i_n)]\)表示最后一笔颜色为k,各颜色还剩.... in支的时候,颜色段数的期望值。

这样并不能递推,还缺一个辅助的状态\(p[k][(i_1,...i_n)]\), 表示到达当前状态的概率。

\(code:\)(已更新为\(mycode\))

#include<cstdio> 
#include<iostream> 
#include<algorithm> 
#include<ctype.h> 
#include<queue> 
#include<string.h> 
#include<vector> 
using namespace std; 

char buf[1<<20],*p1,*p2; 
inline char gc() 
{ 
    return getchar(); 
    return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<20,stdin))==p1?0:*p1++; 
} 

template<typename T> 
inline void read(T &x) 
{ 
    char tt; 
    while(!isdigit(tt=gc()));x=tt-'0'; 
    while(isdigit(tt=gc())) x=x*10+tt-'0'; 
} 

int n,t[10],tmp;
int a[6];
double p[6][16][16][16][16][16];
double f[6][16][16][16][16][16];
int main()
{
    read(n);
    for(int i=1;i<=n;i++) read(t[i]),tmp+=t[i];
    
	if(t[1]>0)
        f[1][t[1]-1][t[2]][t[3]][t[4]][t[5]]=
        p[1][t[1]-1][t[2]][t[3]][t[4]][t[5]]=1.0*t[1]/tmp;
    if(t[2]>0)
        f[2][t[1]][t[2]-1][t[3]][t[4]][t[5]]=
        p[2][t[1]][t[2]-1][t[3]][t[4]][t[5]]=1.0*t[2]/tmp;
    if(t[3]>0)
        f[3][t[1]][t[2]][t[3]-1][t[4]][t[5]]=
        p[3][t[1]][t[2]][t[3]-1][t[4]][t[5]]=1.0*t[3]/tmp;
    if(t[4]>0)
        f[4][t[1]][t[2]][t[3]][t[4]-1][t[5]]=
        p[4][t[1]][t[2]][t[3]][t[4]-1][t[5]]=1.0*t[4]/tmp;
    if(t[5]>0)
        f[5][t[1]][t[2]][t[3]][t[4]][t[5]-1]=
        p[5][t[1]][t[2]][t[3]][t[4]][t[5]-1]=1.0*t[5]/tmp;

    
    for(int sum=tmp-1;sum>=1;sum--)
    for(int i=1;i<=5;i++)
    for(a[1]=sum-t[2]-t[3]-t[4]-t[5],a[1]=a[1]<0?0:a[1];a[1]<=t[1]-(i==1)&&a[1]<=sum;a[1]++)
    for(a[2]=sum-a[1]-t[3]-t[4]-t[5],a[2]=a[2]<0?0:a[2];a[2]<=t[2]-(i==2)&&a[1]+a[2]<=sum;a[2]++)
    for(a[3]=sum-a[1]-a[2]-t[4]-t[5],a[3]=a[3]<0?0:a[3];a[3]<=t[3]-(i==3)&&a[1]+a[2]+a[3]<=sum;a[3]++)
    for(a[4]=sum-a[1]-a[2]-a[3]-t[5],a[4]=a[4]<0?0:a[4];a[4]<=t[4]-(i==4)&&a[1]+a[2]+a[3]+a[4]<=sum;a[4]++)
    {
        a[5]=sum-a[1]-a[2]-a[3]-a[4];
//        printf("%d %d %d %d %d\n",a[1],a[2],a[3],a[4],a[5]);
        if(i==5&&a[5]==t[5]) continue;
        double tf=f[i][a[1]][a[2]][a[3]][a[4]][a[5]];
        double tp=p[i][a[1]][a[2]][a[3]][a[4]][a[5]];
//        printf("%lf %lf %d\n",tf,tp,sum);
        tf/=tp,tp/=sum;
        if(tp==0) continue;
        if(a[1]>0)
        {
            f[1][a[1]-1][a[2]][a[3]][a[4]][a[5]]+=(tf+(i!=1))*tp*a[1];
            p[1][a[1]-1][a[2]][a[3]][a[4]][a[5]]+=tp*a[1];
        }
        if(a[2]>0)
        {
            f[2][a[1]][a[2]-1][a[3]][a[4]][a[5]]+=(tf+(i!=2))*tp*a[2];
            p[2][a[1]][a[2]-1][a[3]][a[4]][a[5]]+=tp*a[2];
        }
        if(a[3]>0)
        {
            f[3][a[1]][a[2]][a[3]-1][a[4]][a[5]]+=(tf+(i!=3))*tp*a[3];
            p[3][a[1]][a[2]][a[3]-1][a[4]][a[5]]+=tp*a[3];
        }
        if(a[4]>0)
        {
            f[4][a[1]][a[2]][a[3]][a[4]-1][a[5]]+=(tf+(i!=4))*tp*a[4];
            p[4][a[1]][a[2]][a[3]][a[4]-1][a[5]]+=tp*a[4];
        }
        if(a[5]>0)
        {
            f[5][a[1]][a[2]][a[3]][a[4]][a[5]-1]+=(tf+(i!=5))*tp*a[5];
            p[5][a[1]][a[2]][a[3]][a[4]][a[5]-1]+=tp*a[5];
        }
    }
    double ans=0;
    for(int i=1;i<=5;i++)
    ans+=f[i][0][0][0][0][0];
    printf("%.18lf",ans);
} 

T2 Too Simple

题解:造出最短路树,然后树上倍增;

\(code:\)

#include<cstdio> 
#include<algorithm> 
#include<ctype.h>  
#include<vector> 
#include<queue> 
#include<cstring> 
#define lowbit(x) (x&-x) 
#define ll long long
#define ld double 
#include<map> 
#define inf 1e9+9
#include<stdlib.h> 
#include<ctime> 
using namespace std; 

char buf[1<<20],*p1,*p2; 
inline char gc() 
{ 
//    return getchar(); 
    return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<20,stdin))==p1?0:*p1++; 
} 

template<typename T> 
inline void read(T &x) 
{ 
    char tt; 
    bool flag=0; 
    while(!isdigit(tt=gc())&&tt!='-'); 
    tt=='-'?(flag=1,x=0):(x=tt-'0'); 
    while(isdigit(tt=gc())) x=x*10+tt-'0'; 
    if(flag) x=-x; 
} 

struct node{
	int x,len;
	inline node(int a=0,int b=0)
	{x=a,len=b;}
	inline bool operator<(node a)const
	{return len>a.len;}
};

const int maxn=100002;
int n,m,que;
int log_[maxn],fa[maxn][20],f[maxn][20],dep[maxn];
int dis1[maxn],dis2[maxn];
vector<node>G[maxn],g[maxn];

void djs1()
{
	priority_queue<node>q;
	for(int i=1;i<=n;i++) dis1[i]=inf;
	dis1[1]=0;q.push(node(1,0));
	while(!q.empty())
	{
		int x=q.top().x;
		int len=q.top().len;q.pop();
		if(dis1[x]!=len) continue;
		for(int i=G[x].size()-1;i>=0;i--)
		{
			int p=G[x][i].x;
			len=G[x][i].len;
			if(dis1[p]<=dis1[x]+len) continue;
			dis1[p]=dis1[x]+len;
			q.push(node(p,dis1[p]));
		}
	}
}

void djs2()
{
	priority_queue<node>q;
	for(int i=1;i<=n;i++) dis2[i]=inf;
	dis2[n]=0;q.push(node(n,0));
	while(!q.empty())
	{
		int x=q.top().x;
		int len=q.top().len;q.pop();
		if(dis2[x]!=len) continue;
		for(int i=g[x].size()-1;i>=0;i--)
		{
			int p=g[x][i].x;
			len=g[x][i].len;
			if(dis2[p]<=dis2[x]+len) continue;
			dis2[p]=dis2[x]+len;
			q.push(node(p,dis2[p]));
		}
	}
	for(int i=1;i<=n;i++) f[i][0]=dis2[i];
}

void bfs()
{
	queue<int>q;q.push(1);
	while(!q.empty())
	{
		int x=q.front();q.pop();
		for(int i=1;i<=log_[n];i++)
		if(fa[x][i-1])
		fa[x][i]=fa[fa[x][i-1]][i-1],f[x][i]=min(f[fa[x][i-1]][i-1],f[x][i-1]);
		else break;
		
		for(int i=G[x].size()-1;i>=0;i--)
		{
			int p=G[x][i].x;
			int len=G[x][i].len;
			if(dis1[p]!=dis1[x]+len) continue;
			dep[p]=dep[x]+1,fa[p][0]=x;q.push(p);
		}
	}
}

void solve1(int x,int y)//深度 
{
	int ans=inf;
	if(dep[x]<y){puts("-1");return;}
	
	for(int i=log_[n];i>=0;i--)
	if(dep[fa[x][i]]>=y)
	ans=min(f[x][i],ans),
	x=fa[x][i];
	ans=min(ans,f[x][0]);
	printf("%d\n",ans);
}

void solve2(int x,int y)//长度 
{
	int ans=inf;
	if(dis1[x]<y){puts("-1");return;}
	
	for(int i=log_[n];i>=0;i--)
	if(dis1[fa[x][i]]>=y)
	ans=min(f[x][i],ans),
	x=fa[x][i];
	ans=min(ans,f[x][0]);
	printf("%d\n",ans);
}

int main()
{
	read(n),read(m),read(que);log_[0]=-1;
	for(int i=1;i<=n;i++) log_[i]=log_[i>>1]+1;
	for(int i=1;i<=m;i++)
	{
		int x,y,len1,len2;
		read(x),read(y),read(len1),read(len2);
		G[x].push_back(node(y,len1));
		G[y].push_back(node(x,len1));
		g[x].push_back(node(y,len2));
		g[y].push_back(node(x,len2));
	}
	djs1();djs2();bfs();dep[0]=-1,dis1[0]=-1;
	while(que--)
	{
		int opt,x,y;
		read(opt),read(x),read(y);
		if(opt==1) solve1(x,y);
		if(opt==2) solve2(x,y);
	}
}


posted @ 2018-10-06 23:26  Katoumegumi  阅读(86)  评论(0编辑  收藏  举报
返回顶部