【比赛报告】2018.10.24校赛[长乐一中Day1] NOIP练习赛卷二十一

在这里插入图片描述


在这里插入图片描述

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=3e4+10,M=5e2+10,sed=31,SED=131,mod=70177,MOD=92311;
int n,m,p,q,ans,tot,hd[mod],nx[N*2],ver[N*2],cnt[N*2],Hash[N],HASH[N];
struct node{
	char s[M];
	inline bool operator<(const node&rhs)const{
	return strcmp(s,rhs.s)<0;}
}a[N];
inline void Insert(const int &x,const int &y)
{
	for(int i=hd[x];i;i=nx[i])
	    if(ver[i]==y){++cnt[i];return;}
	nx[++tot]=hd[x];hd[x]=tot;ver[tot]=y;cnt[tot]=1;
	return;
}
inline int query(const int &x,const int &y)
{
	for(int i=hd[x];i;i=nx[i])
	    if(ver[i]==y)return cnt[i];
	return 0;
}
inline void solve1()
{
	int tmp,TMP;ans=-1;
	for(int i=0;i<n;i++)
	{
		tmp=TMP=0;
		for(int j=0;j<m;j++)
		{
			tmp=(tmp*sed+(a[i].s[j]=='N'))%mod;
			TMP=(TMP*SED+(a[i].s[j]=='N'))%MOD;
		}
		Hash[i]=tmp,HASH[i]=TMP;
		Insert(tmp,TMP);
	}
	for(int i=0;i<n;i++)
	    if(query(Hash[i],HASH[i])==p)//当成满分有p个 
	    {
	    	tmp=TMP=0;
	    	for(int j=0;j<m;j++)//求出零分答案 
	    	{
	    		tmp=(tmp*sed+(a[i].s[j]=='Y'))%mod;
	    		TMP=(TMP*SED+(a[i].s[j]=='Y'))%MOD;
			}
			if(query(tmp,TMP)==q){ans=i;break;}//符合题意 
		}
	if(ans!=-1)printf("%s\n",a[ans].s);
	else puts("-1");
	return;
}
char cur[M];
inline void solve2()
{
	int tmp,TMP;ans=-1;
	for(int i=0;i<n;i++)
	{
		tmp=TMP=0;
		for(int j=0;j<m;j++)
		{
			tmp=(tmp*sed+(a[i].s[j]=='N'))%mod;
			TMP=(TMP*SED+(a[i].s[j]=='N'))%MOD;
		}
		Hash[i]=tmp,HASH[i]=TMP;
		Insert(tmp,TMP);
	}
	for(int i=n-1;i>=0;i--)//枚举零分答案,所以字典序要反着来
	    if(query(Hash[i],HASH[i])==q)
		{
			tmp=TMP=0;
			for(int j=0;j<m;j++)
			{
				tmp=(tmp*sed+(a[i].s[j]=='Y'))%mod;
				TMP=(TMP*SED+(a[i].s[j]=='Y'))%MOD;
			}
			if(query(tmp,TMP)==p){ans=i;break;}
		} 
	if(ans!=-1)
	{
		for(int i=0;i<m;i++)
		    cur[i]=a[ans].s[i]=='N'?'Y':'N';
		printf("%s\n",cur);
	}
	else puts("-1");
	return;
}
inline void solve3()
{
	int tmp,TMP;
	for(int i=0;i<n;i++)
	{
		tmp=TMP=0;
		for(int j=0;j<m;j++)
		{
			tmp=(tmp*sed+(a[i].s[j]=='N'))%mod;
			TMP=(TMP*SED+(a[i].s[j]=='N'))%MOD;
		}
		Insert(tmp,TMP);
		tmp=TMP=0;
		for(int j=0;j<m;j++)
		{
			tmp=(tmp*sed+(a[i].s[j]=='Y'))%mod;
			TMP=(TMP*SED+(a[i].s[j]=='Y'))%MOD;
		}
		Insert(tmp,TMP);
	}
	bool flag=true;
	for(int i=0;i<m;i++)cur[i]='N';
	do{
		tmp=TMP=0;
		for(int j=0;j<m;j++)
		{
			tmp=(tmp*sed+(cur[j]=='N'))%mod;
			TMP=(TMP*SED+(cur[j]=='N'))%MOD;
		}
		if(query(tmp,TMP)==0){flag=true;break;}//没有在满分和零分里面出现过 
		flag=false;
		for(int j=m-1;j>=0;j--)
		{
			if(cur[j]=='Y')cur[j]='N';//已经修改过一次的部分无解
			else{cur[j]='Y';flag=true;break;}//没有修改的给它修改了,可能存在解 
		}
	}while(flag);
	if(flag)printf("%s\n",cur);
	else puts("-1");
	return;
}
int main()
{
	//freopen("in.txt","r",stdin);
	scanf("%d%d%d%d",&n,&m,&p,&q);
    for(int i=0;i<n;i++)
        scanf("%s",a[i].s);
    sort(a,a+n);
    if(p)solve1();
    else if(q)solve2();
    else solve3();
    return 0;
}

在这里插入图片描述


在这里插入图片描述

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=1001;
const int M=1024;
const int power=9;
const int base=1e9;
struct Bignum{
	int a[50];
	Bignum(){memset(a,0,sizeof(a));}
	void print()
	{
		printf("%d",a[a[0]]);
		for(int i=a[0]-1;i>0;i--)
		    printf("%0*d",power,a[i]);
		printf("\n");
	}
	void add(int k){if(k||a[0])a[++a[0]]=k;}
}f[2][M][3];
Bignum operator +(const Bignum&p,const Bignum&q)
{
	Bignum c;
	c.a[0]=max(p.a[0],q.a[0]);
	for(int i=1;i<=c.a[0];i++)
	{
		c.a[i]+=p.a[i]+q.a[i];
		c.a[i+1]+=c.a[i]/base;
		c.a[i]%=base;
	}
	if(c.a[c.a[0]+1])c.a[0]++;
	return c;
}
int n,a[N],pre,cur;
int main()
{
	//freopen("in.txt","r",stdin);
	scanf("%d",&n);
	for(int i=n;i;i--) 
	    scanf("%d",&a[i]);
	f[0][1023][0].add(1);
	for(int i=0;i<n;i++)
	{
		cur=pre^1;
		for(int j=0;j<M;j++)
		    for(int k=0;k<=2;k++)
		        f[cur][j][k]=f[pre][j][k];
		for(int j=0;j<M;j++)
		{
			f[cur][j&a[i+1]][1]=f[cur][j&a[i+1]][1]+f[pre][j][0];f[cur][j&a[i+1]][1]=f[cur][j&a[i+1]][1]+f[pre][j][1];
		    f[cur][j^a[i+1]][2]=f[cur][j^a[i+1]][2]+f[pre][j][1];f[cur][j^a[i+1]][2]=f[cur][j^a[i+1]][2]+f[pre][j][2];
		}
		pre^=1;
	}
	f[pre][0][2].print();
	return 0;
}

在这里插入图片描述
在这里插入图片描述


在这里插入图片描述

#include<cstdio>
#include<queue>
#include<cstring>
#include<algorithm>
using namespace std;
#define MP(a,b) make_pair(a,b)
typedef long long ll;
typedef pair<int,int> pii;
template<class T>inline void read(T&x)
{
	x=0;int f=0;char ch=getchar();
	while(ch<'0'||ch>'9')f|=ch=='-',ch=getchar();
	while(ch>='0'&&ch<='9')x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
	if(f)x=-x;
}
const int N=51,M=201,K=20001;
int Case,n,m,tot,hd[N],len;
ll T,dis[N][K];//dis[i][j]表示到达i号点,时间为j+p*2d,最小的j+p*2d 
bool vis[N][K];
struct Edge{
	int v,nx,w;
}e[M];
inline void add(int u,int v,int w)
{
	e[++tot].v=v;
	e[tot].nx=hd[u];
	e[tot].w=w;
	hd[u]=tot;
}
inline void spfa()
{
	memset(dis,0x3f,sizeof(dis));
	dis[0][0]=0;queue<pii>q;q.push(MP(0,0));
	while(q.size())
	{
		pii tmp=q.front();q.pop();
		int u=tmp.first,w=tmp.second;vis[u][w]=false;
		for(int i=hd[u];i;i=e[i].nx)
		{
			int v=e[i].v;int neww=dis[u][w]+e[i].w;
			if(dis[v][neww%len]>neww)
			{
				dis[v][neww%len]=neww;
				if(!vis[v][neww%len])
				{
					vis[v][neww%len]=1;q.push(MP(v,neww%len));
				}
			}
		}
	}
}
int main()
{
	//freopen("in.txt","r",stdin);
    read(Case);
    while(Case--)
    {
    	read(n);read(m);read(T);
    	memset(hd,0,sizeof(hd));tot=0;
    	for(int i=1,u,v,w;i<=m;i++)
    	    read(u),read(v),read(w),add(u,v,w),add(v,u,w);
    	if(!hd[0])puts("Impossible");
    	else
    	{
    		len=10001;
    		for(int i=hd[0];i;i=e[i].nx)
    		    len=min(len,e[i].w);
    		len*=2;spfa();
    		if(dis[n-1][T%len]<=T)puts("Possible");
    		else puts("Impossible");
		}
	}
	return 0;
}

赛后总结

T1又开始瞎JB乱想,在那里琢磨怎么确定每个问题的解……其实直接枚举每个解为正解或0分就可以了。
T2最开始写的是顺着扫一遍倒着扫一遍再枚举分点的DP,又是莫名其妙的错了。
T3也是感觉非常的迷,没想到这种做法。
或许我真的就只是嘴硬吧。三道题都有人AC,我却都不行。感觉他们在不停的进步,我却连门都没摸到。
或许我真的就只是嘴硬吧。

猜你喜欢

转载自blog.csdn.net/qq_41958841/article/details/83377457