ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

多校冲刺 NOIP 20211113 模拟 (29)

2021-11-13 21:34:06  阅读:153  来源: 互联网

标签:ch NOIP 20211113 int 29 long while inline getchar


多校冲刺 NOIP 20211113 模拟 (29)

T4原题忘记如何统计答案,被迫暴力。。。。

T1 子集和

签到题,直接背包就行了

Code
#include<bits/stdc++.h>
#define int long long
using namespace std;
inline int read()
{
	int x=0,f=1;char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
	return x*f;
}
const int maxn=1e5+5;
int n,b[maxn],m,a[maxn],top;
int bb[maxn],sum;
signed main()
{
	freopen("subset.in","r",stdin);
	freopen("subset.out","w",stdout);
	n=read();m=read();
	for(int i=0;i<=m;i++) b[i]=read();
	int tmp=1; bb[0]=1;
	while(tmp<=m)
	{
		while(!b[tmp]) tmp++;
		int num=b[tmp]-bb[tmp];
		if(num)
		{
			int x=tmp;
			for(int i=1;i<=num;i++)
			{
				a[++top]=tmp;
				for(int v=m;v>=tmp;v--)
				bb[v]+=bb[v-tmp];
			}
		}
		tmp++;	
	}
	for(int i=1;i<=top;i++) printf("%lld ",a[i]);
}

T2 异或

有许多不同的做法,这里给出我考场上的做法,

我们首先对所有点建出一棵 \(Trie\) 树,再将每个点依次删掉顺便统计答案,

答案肯定是被删的与没有被删的点组合出的答案,那么再维护这个点被删掉的与没有被删掉的个数

以及这一层所有左子树删掉的与右子树没被删掉的乘积和,右子树删掉与左子树没被删掉的乘积和

然后统计答案就好了

Code
#include<bits/stdc++.h>
#define ll long long
using namespace std;
inline int read()
{
	int x=0,f=1;char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
	return x*f;
}
const int maxn=5e5+5;
int a[maxn],n;
namespace sub{
	ll ans=0;
	struct Trie{
		int tr[maxn*30][2],root,cnt,ws[maxn*30],ys[maxn*30];ll cj[40][2];
		inline void init(){cnt=1;root=1;}
		inline void insert(int x)
		{
			int u=root;
			for(int i=30;i>=0;i--)
			{
				int val=(x&(1<<i))?1:0;
				if(x&(1<<i)) val=1;
				else val=0;
				ws[u]++;
				if(!tr[u][val]) tr[u][val]=++cnt;
				u=tr[u][val];
			}
			ws[u]++;
		}
		inline void getans(int x)
		{
			int u=root;
			for(int i=30;i>=0;i--)
			{
				int val=(x&(1<<i))?1:0;
				if(x&(1<<i)) val=1;
				else val=0;
				ws[u]--;ys[u]++;
				if(val) ans+=cj[i][0]; else ans+=cj[i][1];
				if(val)
				{
					cj[i][1]-=1ll*ws[tr[u][1]]*ys[tr[u][0]];
					cj[i][1]+=1ll*(ws[tr[u][1]]-1)*ys[tr[u][0]];
					cj[i][0]-=1ll*ws[tr[u][0]]*ys[tr[u][1]];
					cj[i][0]+=1ll*ws[tr[u][0]]*(ys[tr[u][1]]+1);
				}
				else
				{
					cj[i][1]-=1ll*ws[tr[u][1]]*ys[tr[u][0]];
					cj[i][1]+=1ll*ws[tr[u][1]]*(ys[tr[u][0]]+1);
					cj[i][0]-=1ll*ws[tr[u][0]]*ys[tr[u][1]];
					cj[i][0]+=1ll*(ws[tr[u][0]]-1)*ys[tr[u][1]];
				}
				u=tr[u][val];
			}
			ws[u]--;ys[u]++;
		}
	}T;
	inline void main()
	{
		T.init();
		for(int i=1;i<=n;i++) T.insert(a[i]);
		for(int i=1;i<=n;i++) T.getans(a[i]);
		printf("%lld\n",ans);
	}
}
signed main()
{
	freopen("xor.in","r",stdin);
	freopen("xor.out","w",stdout);
	n=read();
	for(int i=1;i<=n;i++) a[i]=read();
	sub::main();return 0;
}

T3 异或 2

知道个柿子就能70了,剩下就是写高精,真jb烦

Code
#include<bits/stdc++.h>
#define LL __int128
#define ULL __uint128_t
#define int long long
using namespace std;
inline int read()
{
	int x=0,f=1;char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
	return x*f;
}
const int base=10000000000000000ll;
struct gj{
	int l,c[101]; ULL has; gj(){}
	gj(int x){memset(c,0,sizeof(c));l=1;c[1]=x;}
	inline void geths(){has=l; for(int i=1;i<=l;i++) has*=c[i];}
	inline void print(){printf("%lld",c[l]);for(int i=l-1;i>0;i--)printf("%016lld",c[i]);puts("");}
	inline gj operator+(const gj &a)const
	{
		gj res=gj(0); res.l=max(l,a.l); for(int i=1;i<=res.l;i++)
		{res.c[i]+=c[i]+a.c[i];res.c[i+1]+=res.c[i]/base;res.c[i]%=base;}
		if(res.c[res.l+1]) ++res.l; res.geths(); return res;
	}
	inline gj operator-(const int &a)const
	{
		gj res=gj(0);res.l=l;for(int i=1;i<=l;i++)res.c[i]=c[i];
		int pos=1;res.c[1]-=a;
		while(res.c[pos]<0){res.c[pos]+=base;++pos;--res.c[pos];}
		if(!res.c[res.l])--res.l;res.geths();return res;
	}
	inline gj operator*(const int &a)const
	{
		gj res=gj(0); res.l=l;for(int i=1;i<=res.l;i++)
		{res.c[i]+=c[i]*a;res.c[i+1]+=res.c[i]/base;res.c[i]%=base;}
		if(res.c[res.l+1])++res.l;res.geths();return res;
	}
	inline gj operator/(const int &a)const
	{
		gj res=gj(0);res.l=l;for(int i=1;i<=l;i++)res.c[i]=c[i];
		if(res.c[1]&1)--res.c[1];
		for(int i=l;i;i--){if(res.c[i]&1) res.c[i-1]+=base;res.c[i]/=a;}
		if(!res.c[l]) --res.l; res.geths(); return res;
	}
}n;
map<ULL,gj>mp; 
inline gj Read()
{
	char ch[1000];
	gj res=gj(0); scanf("%s",ch+1); int len=strlen(ch+1);
	for(int i=1;i<=len;i++) res=res*10+gj(ch[i]-'0');
	return res;
}
inline gj dfs(gj now)
{
	if(now.l<=1&&now.c[1]<=0) return mp[now.has]=gj(0);
	if(mp.find(now.has)!=mp.end()) return mp[now.has];
	gj k=now/2;if(now.c[1]&1) mp[now.has]=dfs(k)*4+k*6;
	else mp[now.has]=dfs(k)*2+dfs(k-1)*2+k*4-4;
	return mp[now.has];
}
signed main()
{
	freopen("rox.in","r",stdin);
	freopen("rox.out","w",stdout);
	gj n=Read();dfs(n).print();
}

T4 卡牌游戏

原题,基环树+换根dp,对于每个联通块求出最小结果及其方案,乘一块就行了

Code
#include<bits/stdc++.h>
#define int long long
using namespace std;
inline int read()
{
	int x=0,f=1;char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
	return x*f;
}
const int maxn=2e5+5,mod=998244353;
int head[maxn],f[3][maxn],num=1,n,m;
struct edge{int to,nxt,v;}e[maxn<<1];
inline void add(int x,int y,int val)
{e[++num]=(edge){y,head[x],val};head[x]=num;}
namespace solve1{
	int dian,bian;bool vis[maxn];
	inline void dfs(int x,int fa)
	{
		dian++;vis[x]=1;for(int i=head[x];i;i=e[i].nxt)
		{bian++;int y=e[i].to;if(y!=fa&&!vis[y])dfs(y,x);}
	}
	inline bool pd()
	{	
		memset(vis,0,sizeof(vis));for(int i=1;i<=n*2;i++)
		if(!vis[i]){dian=bian=0;dfs(i,0);if(dian*2<bian)return false;}
		return true;
	}
}
namespace solve2{
	bool v[maxn];vector<int>tmp;
	int st,en,ned;
	inline void dfs1(int x,int fa)
	{
		v[x]=1;f[1][x]=0;for(int i=head[x];i;i=e[i].nxt)
		if(e[i].to!=fa){int y=e[i].to;
		if(!v[y]){dfs1(y,x);f[1][x]+=f[1][y]+e[i].v;}
		else st=x,en=y,ned=i;}
	}
	inline void dfs2(int x,int fa)
	{
		tmp.push_back(f[2][x]);
		for(int i=head[x];i;i=e[i].nxt)
		if(e[i].to!=fa&&i!=ned&&i!=(ned^1))
		{
			int y=e[i].to;
			if(e[i].v) f[2][y]=f[2][x]-1;
			else f[2][y]=f[2][x]+1;
			dfs2(y,x);
		}
	}
	signed ppp()
	{
		int minn=0,ans=0,ans2=1;
		for(int i=1;i<=2*n;i++)
		if(!v[i])
		{
			st=en=ned=-1;tmp.clear();minn=0;
			dfs1(i,0);f[2][i]=f[1][i];dfs2(i,0);
			if(st==-1)
			{	
				sort(tmp.begin(),tmp.end());
				for(int i=0;i<tmp.size();i++)
				if(tmp[i]==tmp[0])minn++;else break;
				ans+=tmp[0];
			}
			else
			{
				ned%=2;
				if(f[2][st]+ned==f[2][en]+(ned^1)) minn=2;
				else minn=1;
				ans+=min(f[2][st]+ned,f[2][en]+(ned^1));
			}
			ans2=(ans2*minn)%mod;
		}
		printf("%lld %lld\n",ans,ans2);
		return 0;
	}
}
signed main()
{
	freopen("card.in","r",stdin);
	freopen("card.out","w",stdout);
	n=read();num=1;
	for(int i=1;i<=n;i++)
	{
		int x=read(),y=read();
		add(x,y,1);
		add(y,x,0);
	}
	if(!solve1::pd()){puts("-1 -1");return 0;}
	solve2::ppp();
}

标签:ch,NOIP,20211113,int,29,long,while,inline,getchar
来源: https://www.cnblogs.com/JYFHYX/p/15549824.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有