今天考的内容,怎么说呢,都有这样的一个过程:读题(哎呀这题什么意思)->理解题(哎呀这题怎么这么简单)->看一眼数据范围(哎呀这道题怎么这么毒瘤),今天的题都不是难,是难拿高分,写暴力的思路一下子就出来了,然后默默的看着数据范围舍弃掉想法......

话说11号信息奥赛的就要都来学校集训了,就都能一起来受虐了qwq

T1:李时珍的皮肤衣

暑期集训第八天(6-29)模拟赛幸存者实录及总结

 

 

 这道题是这次考试之中唯一可做的一道题了,我们想象一下,如果最里层的衣服被照到了,那么最外层的衣服一定都已经经历过了若干次的变化,且此时他们都是透明的,且最后一次照射之后最内层的衣服变为透明,其余的都成为了不透光的,而我们从表格中可以看到每一次操作之后就相当于数字的大小减了1,于是操作的次数就是2^n-2^(n-1)+1,即2^(n-1)+1,加一是因为要算上第一天,推出了式子就可以进行计算了,当然直接计算是不可取的,要用矩阵快速幂.

#include<bits/stdc++.h>
unsigned long long n;
unsigned long long POW(unsigned long long x,unsigned long long cnt){
	unsigned long long ans=1;
	while(cnt){
		if(cnt & 1) ans=(ans*x)%n;
		cnt>>=1;
		x=(x*x)%n;
		//printf("%llu %llu\n",ans,x);
	}
	return ans%n;
}
int main(){
	scanf("%llu",&n);
	printf("%llu\n",(POW(2,n-1)+1)%n);
	return 0;
}
//其实并不用开ull,ll即可

 T2:马大嘴的废话

暑期集训第八天(6-29)模拟赛幸存者实录及总结

 

这道题在考试的时候不想写暴力,但是想了近一个小时还是没有头绪,只好打了一个暴力拿了60pts,这道题大佬们都用的什么"Hash","AC自动机",这些我都不会,于是用老师讲的tire字典树进行计算,这是一个比较久远的内容了,但是还是有大佬想到了(但想法被另一个大佬封杀了),所以这道题好像考试时并没有人用tire树,对于一个输入的字符串我们依次存原串,去掉第一个字符的串...以此类推,之后考虑处理重复的情况,我们在增加字符串的时候加上一个编号,如果编号重复就不要再增加该串的增加次数了.

#include<bits/stdc++.h>
using namespace std;
const int N=5e5+100;
int tire[N][26],mark[N][26],cnt[N][26];
char str[25];
int n,m,tot;
void Insert(int pos,int end,int id){
	int now=0;
	while(pos<end){
		int t=str[pos]-'a';
		if(!tire[now][t]){
			tire[now][t]=++tot;
			mark[now][t]=id;
			cnt[now][t]=1;
		}
		else{
			if(mark[now][t]!=id){
				mark[now][t]=id;
				++cnt[now][t];
			}
		}
		now=tire[now][t];
		++pos;
	}
}
int search(char *a){
	int len=strlen(a);
	int now=0,ans=0;
	for(int i=0;i<len;++i){
		if(!tire[now][a[i]-'a']) return 0;
		ans=cnt[now][a[i]-'a'];
		now=tire[now][a[i]-'a'];
	}
	return ans;
}
int main(){
	scanf("%d",&n);
	for(int i=0;i<n;++i){
		scanf(" %s",str);
		int len=strlen(str);
		for(int j=0;j<len;++j)
			Insert(j,len,i);
	}
	scanf("%d",&m);
	while(m--){
		scanf(" %s",str);
		printf("%d\n",search(str));
	}
	return 0;
}

 T3:SSY的队列

暑期集训第八天(6-29)模拟赛幸存者实录及总结

 

 emm......这道题现在的正解我还不会写,因为要用到Hash,而我还不会,只能去拿状压的70pts......但是考完试后发现拿70分的人都非常少是怎么回事,状压都写挂了???其实要当状压写的话这道题就没有什么好说的了,和之前做过考过的一道"互不侵犯"神之类似,都是预处理出第一层,之后把最终的状态进行累加,但是状态要改一下,dp[i][j]表示状态为i的最后一个人为j时的答案,有状态转移dp[j|(1<<(i-1))][i]=(dp[j|(1<<(i-1))][i]+dp[j][k]) % M;之后就直接看代码吧.

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int Mod,n,a[50];
ll M=1234567891;
ll dp[1<<23][31];
int main(){
	scanf("%d",&n);
	if(n==0){
		printf("1\n");
		return 0;
	}
	for(int i=1;i<=n;++i) scanf("%d",&a[i]);
	scanf("%d",&Mod);
	int ed=(1<<n)-1;
	for(int i=1;i<=n;++i)
		dp[1<<(i-1)][i]=1;
	for(int j=0;j<=ed;++j)
		for(int i=1;i<=n;++i)
			for(int k=1;k<=n;++k){
				if(i==k) continue;
				if(!(j & (1<<(k-1)))) continue;
				if(j & (1<<(i-1))) continue;
				if(abs(a[k]-a[i])%Mod==0) continue;
				dp[j|(1<<(i-1))][i]=(dp[j|(1<<(i-1))][i]+dp[j][k]) % M;
			}
	ll ans=0;
	for(int i=1;i<=n;++i)
		ans=(ans+dp[ed][i])%M;
	printf("%lld\n",ans);
	return 0;
}

 T4:清理牛棚

暑期集训第八天(6-29)模拟赛幸存者实录及总结

 

 这道题听说要用单调队列优化线性dp?这些统统不会,打一个map的区间dp直接走人(数组开不下只好用mapQAQ),STL果然没让我失望,T了只得了两个点的分......我会向线性dp屈服吗?当然不会,这里安利一个最短路求法,对于每头猪从他开始的天数到结束的那天建一条边权为花费的边,且每个点都向前一个点连一条边权为0的边,这样就相当与去拼一个M到E的方案,从M跑最短路,如果E可以达到,输出答案即可,反之输出-1

#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=3e6+10;
struct Node{
	int next,to,dis;
}edge[N];
int Head[N],tot;
void Add(int x,int y,int z){
	edge[++tot].to=y;
	edge[tot].next=Head[x];
	edge[tot].dis=z;
	Head[x]=tot;
}
struct Edge{
	int dis,id;
	Edge(int x,int y){
		id=x;dis=y;
	}
	bool operator < (const Edge &a)const{
		return a.dis<dis;
	}
};
int dis[N],vis[N];
priority_queue<Edge>q;
void dijkstra(int x){
	memset(dis,0x3f,sizeof(dis));
	memset(vis,0,sizeof(vis));
	dis[x]=0;q.push(Edge(x,0));
	while(!q.empty()){
		int u=q.top().id;q.pop();
		if(vis[u]) continue;
		vis[u]=true;
		for(int i=Head[u];i;i=edge[i].next){
			int v=edge[i].to;
			if(dis[v]>dis[u]+edge[i].dis){
				dis[v]=dis[u]+edge[i].dis;
				q.push(Edge(v,dis[v]));
			}
		}
	}
}
signed main(){
	int n,m,e;
	scanf("%lld%lld%lld",&n,&m,&e);
	for(int i=1;i<=n;++i){
		int x,y,z;
		scanf("%lld%lld%lld",&x,&y,&z);
		if(x<m) x=m;
		if(y>e) y=e;
		Add(x,y+1,z);
	}
	for(int i=m;i<e;++i){
		Add(i+1,i,0);
	}
	dijkstra(m);
	if(dis[e+1]==0x3f3f3f3f3f3f3f3f)
		printf("-1\n");
	else printf("%lld\n",dis[e+1]);
	return 0;
}

 然后就是今天的一些练习题啦,没有什么说的,大部分都是一些板子和一些不好调试的题目,但是写出来还是很简单的,这里就不详细说了,

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int agree[505][505][55],dp[505][505][55];
 4 int zhuan(char c){
 5     if(c=='W') return 1;
 6     if(c=='I') return 2;
 7     if(c=='N') return 3;
 8     if(c=='G') return 4;
 9 }
10 int main(){
11     int a,b,c,d;
12     scanf("%d%d%d%d",&a,&b,&c,&d);
13     for(int i=1;i<=a;++i){
14         char ch[5],chh='W';
15         scanf(" %s",ch);
16         agree[zhuan(ch[0])][zhuan(ch[1])][1]=1;
17         agree[1][1][1]=1;
18     }
19     for(int i=1;i<=b;++i){
20         char ch[5],chh='I';
21         scanf(" %s",ch);
22         agree[zhuan(ch[0])][zhuan(ch[1])][2]=1;
23         agree[2][2][2]=1;
24     }
25     for(int i=1;i<=c;++i){
26         char ch[5],chh='N';
27         scanf(" %s",ch);
28         agree[zhuan(ch[0])][zhuan(ch[1])][3]=1;
29         agree[3][3][3]=1;
30     }
31     for(int i=1;i<=d;++i){
32         char ch[5],chh='G';
33         scanf(" %s",ch);
34         agree[zhuan(ch[0])][zhuan(ch[1])][4]=1;
35         agree[4][4][4]=1;
36     }
37     char name[3500];
38     scanf(" %s",name);
39     int n=strlen(name);
40     for(int i=0;i<n;++i) dp[i][i][zhuan(name[i])]=1;
41     for(int d=2;d<=n;++d)
42         for(int i=0,j;(j=i+d-1)<n;++i){
43             for(int k=i;k<j;++k){
44                 for(int u=1;u<=4;++u)    
45                     if(dp[i][k][u]==1)
46                         for(int g=1;g<=4;++g)
47                             if(dp[k+1][j][g]==1)    
48                                 for(int x=1;x<=4;++x)
49                                     if(agree[u][g][x])
50                                         dp[i][j][x]=1;
51             }
52         }
53     int flag=0;
54     for(int i=1;i<=4;++i)
55         if(dp[0][n-1][i]){
56             flag=1;
57             if(i==1) printf("W");
58             if(i==2) printf("I");
59             if(i==3) printf("N");
60             if(i==4) printf("G");
61         }
62     if(!flag) printf("The name is wrong!");
63     return 0;
64 }
P4290 [HAOI2008]玩具取名

相关文章:

  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2021-06-19
猜你喜欢
  • 2022-02-05
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
相关资源
相似解决方案