ZROI 欢度新春娱乐赛

ZROI 欢度新春娱乐赛
WOW!
T1:
在这里插入图片描述
十分easy?
考场上预处理+gcd
大致思路是一个点x-1和y-1互质,那么这个点一定看得见1
70分,原因是要从1枚举到1001才行,因为(如题
源代码

#include<bits/stdc++.h>
using namespace std;
const int N=1005;
int T; 
int c[N][N]={0};
int f[N][N]={0};
int g[N][N]={0}; 
int gcd(int x,int y){
if(x==0) return y;
else return gcd(y%x,x);
}
int can(int x,int y){
if(x==0&&y==0) return 1;
if(x==0||y==0){
if(x+y==1) return 1;
else return 0; 
}
if(gcd(x,y)!=1) return 0;
return 1;
}
void sol(){
for(int i=1;i<=1000;i++){
for(int j=1;j<=1000;j++){
			c[i][j]=can(i-1,j-1);
}
}
for(int i=1;i<=1000;i++){
for(int j=1;j<=1000;j++){
			f[i][j]=f[i][j-1]+c[i][j];
} 
} 
for(int i=1;i<=1000;i++){
for(int j=1;j<=1000;j++){
			g[i][j]=g[i-1][j]+f[i][j];
}
}
}
void Debug(){
for(int i=1;i<=10;i++){
for(int j=1;j<=10;j++){
			cout << c[i][j] << " ";
}
		cout << endl;
}
}
int main(){
//ios::sync_with_stdio(false);
sol();
//Debug();
scanf("%d",&T);
while(T--){
int x,y;
scanf("%d%d",&x,&y);
printf("%d\n",g[x+1][y+1]);
}
return 0;
} 

订正代码:

#include<bits/stdc++.h>
using namespace std;
const int N=1005;
int T; 
int c[N][N]={0};
int f[N][N]={0};
int g[N][N]={0}; 
int gcd(int x,int y){
if(x==0) return y;
else return gcd(y%x,x);
}
int can(int x,int y){
if(x==0&&y==0) return 1;
if(x==0||y==0){
if(x+y==1) return 1;
else return 0; 
}
if(gcd(x,y)!=1) return 0;
return 1;
}
void sol(){
for(int i=1;i<=1001;i++){
for(int j=1;j<=1001;j++){
			c[i][j]=can(i-1,j-1);
}
}
for(int i=1;i<=1001;i++){
for(int j=1;j<=1001;j++){
			f[i][j]=f[i][j-1]+c[i][j];
} 
} 
for(int i=1;i<=1001;i++){
for(int j=1;j<=1001;j++){
			g[i][j]=g[i-1][j]+f[i][j];
}
}
}
void Debug(){
for(int i=1;i<=1001;i++){
for(int j=1;j<=1001;j++){
}
}
}
int main(){
//ios::sync_with_stdio(false);
sol();
//Debug();
scanf("%d",&T);
while(T--){
int x,y;
scanf("%d%d",&x,&y);
printf("%d\n",g[x+1][y+1]);
}
return 0;
} 

T2:

在这里插入图片描述
hard!
考场上想到了暴力DFS
源代码:

#include<bits/stdc++.h>
using namespace std;
#define p 998244353
const int N=500005;
int n,m;
int hed[N],tal[N],val[N],nxt[N],cnt=0;
map<int,map<int,bool> > s;
int ans=0;
void add(int x,int y){
	cnt++;
	tal[cnt]=y;
	nxt[cnt]=hed[x];
	hed[x]=cnt;
}
void zou(int x){
	ans++;
	ans%=p;
for(int i=hed[x];i;i=nxt[i]){
int y=tal[i];
zou(y);
}
}
int main(){
//ios::sync_with_stdio(false);
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++){
int a,b;
scanf("%d%d",&a,&b);
if(s[a][b]==1) continue;
add(a,b);
		s[a][b]=1;
}
for(int i=1;i<=n;i++){
zou(i);
}
printf("%d\n",ans);
return 0;
} 

30分,听取T声一片
正解:
BFS
想想,什么点的入度为0?

起点

那么…
每次先将入度为0的点入队
每次用队里的点去更新另外点
那么,更新完后入度–
如果一个点入度变成了0,则进队
还有一点:重边要判掉
订正代码:

#include<bits/stdc++.h>
using namespace std;
#define p 998244353
typedef long long ll;
const int N=500005;
int n,m;
ll f[N]={0};
map<ll,bool> s;
int d[N]={0}; 
int hed[N],tal[N],nxt[N],cnt=0;
int h=1,t=0;
int q[N*10];
ll ans=0;
void add(int x,int y){
	cnt++;
	tal[cnt]=y;
	nxt[cnt]=hed[x];
	hed[x]=cnt;
}
int main(){
scanf("%d%d",&n,&m); 
while(m--){
int a,b;
scanf("%d%d",&a,&b);
if(s[a*1000000ll+b]==0){
			s[a*1000000ll+b]=1;
add(a,b);
			d[b]++;
}
}
for(int i=1;i<=n;i++){
		f[i]=1;
if(d[i]==0) q[++t]=i;
}
while(h<=t){
int u=q[h];
		h++;
for(int i=hed[u];i;i=nxt[i]){
int v=tal[i];
			d[v]--;
			f[v]+=f[u];
			f[v]%=p;
if(d[v]==0) q[++t]=v;
}
} 
for(int i=1;i<=n;i++) ans+=f[i],ans%=p;
printf("%lld\n",ans);
return 0;
} 

T3:
玄学emm
一开始打了个暴力分块
然后:0!
WHAT?
源代码:

#include<bits/stdc++.h>
using namespace std;
const int N=100005;
const int M=500;
struct node{
int num;
int Rank;
}s[N];

int n,m,Q;
int u=0;
int col[N];
int l[M]={0},r[M]={0};
int LZT[M]={0};
bool cmp(node x,node y){
return x.num<y.num;
}
void doit(int left,int right,int LB,int RB,int NUM){
for(int i=left;i<=right;i++){
if(s[i].Rank>=LB&&s[i].Rank<=RB){
			s[i].num+=NUM;
}
}
sort(s+left,s+right+1,cmp);
}
int sec(int left,int right,int LB,int RB,int NUM){
int u=-1;
for(int i=left;i<=right;i++){
if(s[i].Rank>=LB&&s[i].Rank<=RB){
if(s[i].num<=NUM){
				u=max(u,s[i].num);
}
}
}
return u;
}
int serch(int left,int right,int LB,int RB,int NUM){
int l=left,r=right,ans=-1;
while(l<=r){
int mid=(l+r)>>1;
if(s[mid].num<=NUM) ans=s[mid].num,l=mid+1;
else r=mid-1;
}
return ans;
}
int main(){
//ios::sync_with_stdio(false);
scanf("%d%d%d",&n,&m,&Q);
	u=sqrt(n);
for(int i=1;i<=n;i++) scanf("%d",&col[i]),s[i].Rank=i,s[i].num=col[i];
for(int i=1;i<=u;i++){
		l[i]=r[i-1]+1;
		r[i]=l[i]+u-1;
}
	r[u]=n;
for(int i=1;i<=u;i++){
sort(s+l[i],s+r[i]+1,cmp);
}
while(m--){
int opt;
scanf("%d",&opt);
if(opt==1){
int L,R,X;
scanf("%d%d%d",&L,&R,&X);
for(int i=1;i<=u;i++){
if(r[i]<L) continue;
if(l[i]>R) break;
if(l[i]<=L&&r[i]>=R){
doit(l[i],r[i],L,R,X);
break;
}
if(l[i]<=L&&r[i]>=L){
doit(l[i],r[i],L,R,X);
continue;
}
if(l[i]<=R&&r[i]>=R){
doit(l[i],r[i],L,R,X);
break;
}
				LZT[i]+=X;
}
}
else{
int L,R,ans=-1;
scanf("%d%d",&L,&R);
for(int i=1;i<=u;i++){
if(r[i]<L) continue;
if(l[i]>R) break;
int num;
if(l[i]<=L&&r[i]>=R){
					num=sec(l[i],r[i],L,R,Q-LZT[i]);
}
else if(l[i]<=L&&r[i]>=L){
					num=sec(l[i],r[i],L,R,Q-LZT[i]);
}
else if(l[i]<=R&&r[i]>=R){
					num=sec(l[i],r[i],L,R,Q-LZT[i]);
}
else num=serch(l[i],r[i],L,R,Q-LZT[i]);
				ans=max(ans,num);
}
printf("%d\n",ans);
}
}
return 0;
}   

然后发现add操作失误,再加上一笔卡常技巧就100了。
订正代码:
这里


T4
大水题
具体思路就是模拟
每次×2最好
代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll l,r;
ll ans=0;
int main(){
	//ios::sync_with_stdio(false);
	scanf("%lld%lld",&l,&r);
	while(1){
		if(l>r) break;
		ans++;
		l*=2;
	} 
	printf("%lld\n",ans);
	return 0;
} 

T5
神题
我想到的是:DFS一遍,打出时间戳,同层贡献分别算+快速幂
20分
订不出来,没人A

#include<bits/stdc++.h>
using namespace std;
#define p 1000000007
typedef long long ll;
const int N=500005;
int n;
int hed[N],tal[N],nxt[N],cnt=0;
int dis[N]={0};
ll cont[N]={0};
int opt=0;
ll ans=0;
ll ck=0;
ll out[N];
int Q[N]; 
ll  P[N];
int Rk=0; 
ll qpow(ll x,ll y){
	ll sum=1;
	while(y){
		if(y&1) sum=(sum*x)%p;
		x=(x*x)%p;
		y>>=1;
	}
	return sum;
} 
void add(int x,int y){
	cnt++;
	tal[cnt]=y;
	nxt[cnt]=hed[x];
	hed[x]=cnt;
}
void dfs(int x,int fa){
	dis[x]=dis[fa]+1;
	cont[dis[x]]++;
	P[dis[x]]++;
	if(cont[dis[x]]==1){
		opt++;
	}
	for(int i=hed[x];i;i=nxt[i]){
		int y=tal[i];
		if(y==fa) continue;
		dfs(y,x);
	}
}
int main(){
	//ios::sync_with_stdio(false);
	scanf("%d",&n);
	for(ll i=1;i<n;i++){
		int a,b;
		scanf("%d%d",&a,&b);
		add(a,b);
		add(b,a);
	}
	dfs(1,0);
	//cout << C(5,3) << endl;
	int all=0;
	for(int i=1;i<=opt;i++){
		all=all+cont[i];
	}
	for(int i=1;i<=opt;i++){
		ans=(ans+(cont[i]*qpow(2,all-cont[i]))%p)%p; 
	} 
	printf("%lld\n",ans);
	return 0;
} 
/*
5
1 2
2 3
1 4
1 5
*/

T6
大模拟
考试时为未注意细节,40
源代码:

#include<bits/stdc++.h>
using namespace std;
int n,k,T,m;
char s;
int main(){
	//ios::sync_with_stdio(false);
	scanf("%d%d%d%d",&n,&k,&T,&m);
	scanf("%c",&s);
	if(T-k>1) printf("<< ");
	for(int i=max(1,T-k);i<=min(n,T+k);i++){
		if(i==T) printf("(%d) ",i);
		else printf("%d ",i);
	}
	if(T+k<n) printf(">>");
	printf("\n");
	for(int i=1;i<=m;i++){
		char c[2005];
		int f=0;
		while(c[f+1]=getchar(),c[f+1]!='\n') f++;
		if(c[7]=='>'){
			if(T+k>=n) printf("WARNING\n");
			else{
				for(int j=max(1,n-k);j<=n;j++){
					if(j==max(1,n-k)) printf("<< ");
					if(j==n){
						printf("(%d)\n",j);
						break;
					}
					printf("%d ",j);
				} 
				T=n;
			}
		}
		else if(c[7]=='<'){
			if(T-k<=1) printf("WARNING\n");
			else{
				for(int j=1;j<=min(n,1+k);j++){
					if(j==1){
						printf("(%d) ",j);
						continue;
					}
					printf("%d ",j);
					if(j==min(n,1+k)){
						printf(">>\n");
					}
				} 
				T=n;
			}
		}
		else{
			int num=c[7]-'0';
			for(int j=8;j<=f;j++) num=num*10+c[j]-'0';
			if(num<1||num>n) printf("WARNING\n");
			else if(num>T+k||num<T-k) printf("WARNING\n");
			else{
				if(num-k>1) printf("<< ");
				for(int i=max(1,num-k);i<=min(n,num+k);i++){
					if(i==num) printf("(%d) ",i);
					else printf("%d ",i);
				}
				if(num+k<n) printf(">>");
				printf("\n");
				T=num;
			} 
		}
	}
	return 0;
} 

后来秒发现问题,立马改正
代码:

#include<bits/stdc++.h>
using namespace std;
int n,k,T,m;
char s;
int main(){
	//ios::sync_with_stdio(false);
	scanf("%d%d%d%d",&n,&k,&T,&m);
	scanf("%c",&s);
	if(T-k>1) printf("<< ");
	for(int i=max(1,T-k);i<=min(n,T+k);i++){
		if(i==T) printf("(%d) ",i);
		else printf("%d ",i);
	}
	if(T+k<n) printf(">>");
	printf("\n");
	for(int i=1;i<=m;i++){
		char c[2005];
		int f=0;
		while(c[f+1]=getchar(),c[f+1]!='\n') f++;
		if(c[7]=='>'){
			if(T+k>=n) printf("WARNING\n");
			else{
				for(int j=max(1,n-k);j<=n;j++){
					if(j==max(1,n-k)) printf("<< ");
					if(j==n){
						printf("(%d)\n",j);
						break;
					}
					printf("%d ",j);
				} 
				T=n;
			}
		}
		else if(c[7]=='<'){
			if(T-k<=1) printf("WARNING\n");
			else{
				for(int j=1;j<=min(n,1+k);j++){
					if(j==1){
						printf("(%d) ",j);
						if(j==min(n,1+k)){
							printf(">>\n");
						}
						continue; 
					}
					printf("%d ",j);
					if(j==min(n,1+k)){
						printf(">>\n");
					}
				} 
				T=1;
			}
		}
		else{
			int num=c[7]-'0';
			for(int j=8;j<=f;j++) num=num*10+c[j]-'0';
			if(num<1||num>n) printf("WARNING\n");
			else if(num>T+k||num<T-k) printf("WARNING\n");
			else{
				if(num-k>1) printf("<< ");
				for(int i=max(1,num-k);i<=min(n,num+k);i++){
					if(i==num) printf("(%d) ",i);
					else printf("%d ",i);
				}
				if(num+k<n) printf(">>");
				printf("\n");
				T=num;
			} 
		} 
	} 
	return 0; 
} 

T7
难·DP
好难
有题解来着

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const ll N=5005,M=1e9+7;
ll n;
ll a;
ll b;
ll f[N][N];
ll c[N][N];
void work(void)
{
	//cout << "***" << endl;
	for(int i=0;i<=N;i++) f[i][0]=1;
	for(int i=1;i<N;i++)
	{
		for(int j=1;j<=i&&j<N;j++)
		{
			f[i][j]=(f[i-1][j-1]+f[i-1][j])%M;
		}
	}
	//cout << "***" << endl;
	for(int i=0;i<=N;i++) c[i][i]=1;
	//cout << "***" << endl;
	for(int i=2;i<N;i++)
	{
		for(int j=1;j<i&&j<N;j++)
		{
			c[i][j]=((i-1)*c[i-1][j]%M+c[i-1][j-1])%M;
		}
	}
	//cout << "***" << endl;
}
int main()
{
	work();
	//cout << "***" << endl;
	scanf("%lld%lld%lld",&n,&a,&b);
	if(a+b>n+1) printf("0\n");
	else printf("%lld\n",f[a+b-2][a-1]*c[n-1][a+b-2]%M);
	return 0;
} 

T8
两次dijkstra秒出答案
记得加堆优化
代码


T9
BFS
加上优先队列优化
源代码:

#include<bits/stdc++.h>
using namespace std;
const int N=2005;
int n,m;
char s[N][N];
int f[N][N];
struct ma
{
	int x;
	int y;
};
bool operator <(const ma &a,const ma &b)
{
	return f[a.x][a.y]>f[b.x][b.y];
}
priority_queue<ma> q;
void push(int x,int y)
{
	ma a;
	a.x=x;
	a.y=y;
	q.push(a);
}
int main()
{
	memset(f,-1,sizeof(f));
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++)
		scanf("%s",s[i]+1);//%%%gaolinxiang dalao 的快读快写貌似一行足矣
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=m;j++)
		{
			if(s[i][j]=='+')
			{
				f[i][j]=0;
				push(i,j);
			}	
		}
	}
	
	while(!q.empty())
	{
		ma u=q.top();
		int x=u.x;
		int y=u.y;
		int z=f[x][y];
		q.pop();
		
		//向四个方向拓展 
		
		x=u.x,y=u.y;
		while(x<n&&s[x+1][y]=='.')
		{
			x++;
			if(z+1<f[x][y]||f[x][y]==-1){
				f[x][y]=z+1;
				push(x,y);
			}
		}
	 
		x=u.x,y=u.y;
		while(x>1&&s[x-1][y]=='.')
		{
			x--;
			if(z+1<f[x][y]||f[x][y]==-1){
				f[x][y]=z+1;
				push(x,y);
			}
		}
		
		x=u.x,y=u.y;
		while(y<n&&s[x][y+1]=='.')
		{
			y++;
			if(z+1<f[x][y]||f[x][y]==-1){
				f[x][y]=z+1;
				push(x,y);
			}
		}
		
		x=u.x,y=u.y;
		while(y>1&&s[x][y-1]=='.')
		{
			y--;
			if(z+1<f[x][y]||f[x][y]==-1){
				f[x][y]=z+1;
				push(x,y);
			}
		}
		
	}
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<m;j++)
		{
			if(s[i][j]=='#') printf("# ");
			else if(f[i][j]==-1) printf("X ");
			else printf("%d ",f[i][j]);
		}
		if(s[i][m]=='#') printf("#");
		else if(f[i][m]==-1) printf("X");
		else printf("%d",f[i][m]);
		printf("\n");
	}
	
	return 0;
} 

T10
数论5合1
想看正解的:点这里
我只会30分暴力+40分特判
源代码:

#include<bits/stdc++.h>
using namespace std;
#define p 999911659
typedef long long ll;
int n,m,k;
bool g[1005][1005]={0};
ll f[1005][1005]={0};
ll qpow(ll x,ll y){
	ll ans=1;
	while(y){
		if(y&1) ans=(ans*x)%p;
		x=(x*x)%p;
		y>>=1;
	}
	return ans;
}
void Subtask1(){
	scanf("%d",&k);
	while(k--){
		int l,r;
		scanf("%d%d",&l,&r);
		g[++l][++r]=1;
	}
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			if(i>j) g[i][j]=1;
		}
	}
	for(int i=1;i<=m;i++) if(!g[1][i]) f[1][i]=1;
	for(int i=1;i<=n;i++) if(!g[i][1]) f[i][1]=1;
	for(int i=2;i<=n;i++){
		for(int j=2;j<=m;j++){
			if(g[i][j]) continue;
			f[i][j]=(f[i-1][j]+f[i][j-1])%(p-1);
		}
	}
	printf("%lld\n",qpow(1ll*233,f[n][m]));
}
int main(){
	//ios::sync_with_stdio(false);
	scanf("%d%d",&n,&m);
	if(n<=1000&&m<=1000){
		Subtask1();
	}
	else{
		printf("1\n");
		return 0;
	}
	return 0;
} 

T11
不说了

THE END

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值