CSP-S 2020 题解

怎么说呢 自己还是不太行 明明有370的傻逼分的但是还是挂掉了 现在就是个省二彩笔

算了 就这样吧 反正初中也去不了noip

T1

按照题意模拟即可,考场上脑瘫了哈哈哈没有对拍哈哈哈就忘记了模出来可能会有0这回事哈哈哈出题人nmsl

#include<bits/stdc++.h>
using namespace std;
#define int long long
const int norday[12]={31,28,31,30,31,30,31,31,30,31,30,31};
const int runday[12]={31,29,31,30,31,30,31,31,30,31,30,31};
const int year4=366+365+365+365;
const int run4[4]={366,365,365,365};
const int run41[4]={365,365,365,366};
const int year400=146097;
bool pdrun(int y){
	if(y<0){
		return y%4==-1;
	}
	else if(y<=1582){
		return y%4==0;
	}
	else {
		return ((y%400==0)||(y%4==0&&y%100!=0));
	}
}
int ansy,ansm,ansd;
void getdate(int y,int d){
	if(pdrun(y)){
		int tmp=0;
		for(int i=0;i<12;++i){
			tmp+=runday[i];
			if(tmp>=d){
				tmp-=runday[i];
				ansd=d-tmp;
				ansm=i+1;
				return;
			}
		}
	}
	else {
		int tmp=0;
		for(int i=0;i<12;++i){
			tmp+=norday[i];
			if(tmp>=d){
				tmp-=norday[i];
				ansd=d-tmp;
				ansm=i+1;
				return;
			}
		}
	}
} 
signed main(){
	int Q;
	scanf("%lld",&Q);
	while(Q--){
		int n;
		scanf("%lld",&n);
		n++;
		ansy=-4713;
		if(n<365){
			getdate(-4713,n);
			printf("%lld %lld %lld BC\n",ansd,ansm,abs(ansy));
		}
		else if(n<=1721424){
			ansy+=n/year4*4;
			int tmp=n%year4;
			//cout<<tmp<<endl;
			if(tmp==0)ansy-=4,tmp=year4;
			int sb=0;
			for(int i=0;i<4;++i){
				sb+=run4[i];
				if(sb>=tmp){
					ansy+=i;
					sb-=run4[i];
					sb=tmp-sb;
					getdate(ansy,sb);
					printf("%lld %lld %lld BC\n",ansd,ansm,abs(ansy));
					break;
				}
			}
		}
		else {
			n-=1721424;
			ansy=0;
			if(n<=577737){
				ansy+=n/year4*4;
				int tmp=n%year4;
				if(tmp==0)ansy-=4,tmp=year4;
				int sb=0;
				for(int i=0;i<4;++i){
					sb+=run41[i];
					if(sb>=tmp){
						ansy+=i+1;
						sb-=run41[i];
						sb=tmp-sb;
						getdate(ansy,sb);
						printf("%lld %lld %lld\n",ansd,ansm,abs(ansy));
						break;
					}
				}
			}
			else {
				n-=577737;
				if(n<=78){
					n+=287;
					getdate(1582,n);
					ansy=1582;
					printf("%lld %lld %lld\n",ansd,ansm,abs(ansy));
				}
				else {
					n-=78;
					ansy=1582;
					ansy+=n/year400*400;
					int tmp=n%year400;
					if(tmp==0)ansy-=400,tmp=year400;
					int sb=0;
					for(int i=1583;i<=1583+400-1;++i){
						sb+=365+(((i%400==0)||(i%4==0&&i%100!=0))?1:0);
						if(sb>=tmp){
							ansy+=i-1582;
							sb-=365+(((i%400==0)||(i%4==0&&i%100!=0))?1:0);
							sb=tmp-sb;
							getdate(ansy,sb);
							printf("%lld %lld %lld\n",ansd,ansm,abs(ansy));
							break;
						}
					}
				}
			}
		}
	}
}
/*
8
365
366
1721423
1721424
2299160
2299161
2299238
2299239
*/

T2

显然不用去管饲料是个啥,只需要判断某一位能不能用就可以了(qi互不相同),那么最后\(2^{可以用的位数}-已经有的个数\)即可

注意判k=64和n=0

#include<bits/stdc++.h>
using namespace std;
#define int unsigned long long
int n,m,c,k;
int alla;
bool tag[1000010];
int sum;
signed main(){
	scanf("%llu%llu%llu%llu",&n,&m,&c,&k);
	for(int i=1;i<=n;++i){
		int ai;
		scanf("%llu",&ai);
		alla|=ai;
	}
	//cout<<alla<<endl;
	for(int i=1;i<=m;++i){
		int p,q;
		scanf("%llu%llu",&p,&q);
		if(!((1ull<<p)&alla)){
			if(!tag[p])sum++;
			tag[p]=true;
		}
	}
	//cout<<sum<<endl;
	if(k-sum==64){
		if(n==0)puts("18446744073709551616");
		else printf("%llu\n",(1ull<<63)-n+(1ull<<63));
	}
	else {
		printf("%llu\n",(1ull<<(k-sum))-n);
	}
}

T3

考虑倒着处理,那么就可以把原来的函数序列转换成每个函数分别需要单独执行的次数,也就是系数(这一步也要拓扑序以得到每个函数会把前面的函数乘上几倍)

那么每个函数再用拓扑序一个个往下更新,更新到底层的每个加法函数要执行几次,最后再执行就好了

两次的图刚好是反图

考场上分明都想出来了却不敢写...唉

#include<bits/stdc++.h>
using namespace std;
#define int long long
const int mod=998244353;
int n;
int a[1000010];
int m;
struct func{
	int type;
	int x,v;
}q[1000010];
int tval[1000010];
struct qwq{
	int v;
	int nxt;
}edge[1000010];
int cnt=-1;
int head[1000010];
struct ed{
	int u,v;
}e[1000010];
void add(int u,int v){
	edge[++cnt].nxt=head[u];
	edge[cnt].v=v;
	head[u]=cnt;
}
int ind[1000010];
void topo_solve1(){
	queue<int> qu;
	for(int i=1;i<=m;++i){
		if(!ind[i])qu.push(i);
	}
	while(!qu.empty()){
		int u=qu.front();
		qu.pop();
		for(int i=head[u];~i;i=edge[i].nxt){
			int v=edge[i].v;
			tval[v]=(tval[v]*tval[u])%mod;
			ind[v]--;
			if(!ind[v]){
				qu.push(v);
			}
		}
	}
}
int tot;
int Q;
int que[1000010];
int allt[1000010];
int rea[1000010];
void topo_solve2(){
	queue<int> qu;
	for(int i=1;i<=m;++i){
		if(!ind[i]){
			qu.push(i);
		}
		rea[i]=allt[i];
	}
	while(!qu.empty()){
		int u=qu.front();
		qu.pop();
		int nowk=rea[u];
		for(int i=head[u];~i;i=edge[i].nxt){
			int v=edge[i].v;
			rea[v]=(rea[v]+nowk)%mod;
			ind[v]--;
			if(!ind[v]){
				qu.push(v);
			}
			nowk=(nowk*tval[v])%mod;
		}
	} 
}
signed main(){
	memset(head,-1,sizeof(head));
	scanf("%lld",&n);
	for(int i=1;i<=n;++i)scanf("%lld",&a[i]);
	scanf("%lld",&m);
	for(int i=1;i<=m;++i){
		scanf("%lld",&q[i].type);
		if(q[i].type==1){
			scanf("%lld%lld",&q[i].x,&q[i].v);
			tval[i]=1;
		}
		else if(q[i].type==2){
			scanf("%lld",&q[i].v);
			tval[i]=q[i].v;
		}
		else {
			int cj;
			scanf("%lld",&cj);
			ind[i]=cj;
			for(int j=1;j<=cj;++j){
				int x;
				scanf("%lld",&x);
				add(x,i);
				e[cnt].v=x,e[cnt].u=i;
			}
			tval[i]=1;
		}
	}
	topo_solve1();
	//for(int i=1;i<=m;++i)cout<<i<<":"<<tval[i]<<endl;
	scanf("%lld",&Q);
	for(int i=1;i<=Q;++i)scanf("%lld",&que[i]);
	int k=1;
	allt[que[Q]]=(allt[que[Q]]+k)%mod;
	//cout<<que[Q]<<" "<<allt[que[Q]]<<endl;
	for(int i=Q-1;i>=1;--i){
		k=k*tval[que[i+1]]%mod;
		allt[que[i]]=(allt[que[i]]+k)%mod;
		//cout<<que[i]<<" "<<allt[que[i]]<<endl;
	}
	k=(k*tval[que[1]])%mod;
	memset(head,-1,sizeof(head));
	memset(edge,0,sizeof(edge));
	int tot=cnt;cnt=-1;
	memset(ind,0,sizeof(ind));
	for(int i=0;i<=tot;++i){
		add(e[i].u,e[i].v);
		ind[e[i].v]++;
	}
	topo_solve2();
	for(int i=1;i<=n;++i){
		a[i]=(a[i]*k)%mod;
	}
	for(int i=1;i<=m;++i){
		if(q[i].type==1){
			a[q[i].x]=(a[q[i].x]+(rea[i]*q[i].v)%mod)%mod;
		}
	}
	for(int i=1;i<=n;++i){
		printf("%lld ",a[i]);
	}
	puts("");
}
/*
3
1 2 3
3
1 1 1
2 2
3 2 1 2
2
2 3
*/

T4

还不会,咕咕咕

上一篇:洛谷题单 【数学】编程能力进阶


下一篇:梦幻岛宝珠题解