zoukankan      html  css  js  c++  java
  • 暑期集训第八天(6-29)模拟赛幸存者实录及总结

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

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

    T1:李时珍的皮肤衣

     这道题是这次考试之中唯一可做的一道题了,我们想象一下,如果最里层的衣服被照到了,那么最外层的衣服一定都已经经历过了若干次的变化,且此时他们都是透明的,且最后一次照射之后最内层的衣服变为透明,其余的都成为了不透光的,而我们从表格中可以看到每一次操作之后就相当于数字的大小减了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
    ",ans,x);
    	}
    	return ans%n;
    }
    int main(){
    	scanf("%llu",&n);
    	printf("%llu
    ",(POW(2,n-1)+1)%n);
    	return 0;
    }
    //其实并不用开ull,ll即可
    

     T2:马大嘴的废话

    这道题在考试的时候不想写暴力,但是想了近一个小时还是没有头绪,只好打了一个暴力拿了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
    ",search(str));
    	}
    	return 0;
    }
    

     T3:SSY的队列

     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
    ");
    		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
    ",ans);
    	return 0;
    }
    

     T4:清理牛棚

     这道题听说要用单调队列优化线性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
    ");
    	else printf("%lld
    ",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]玩具取名
     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 const int N=1e6+10;
     4 struct Node{
     5     int from,next,to;
     6 }edge[N];
     7 int Head[N],tot;
     8 void Add(int x,int y){
     9     edge[++tot].to=y;
    10     edge[tot].from=x;
    11     edge[tot].next=Head[x];
    12     Head[x]=tot;
    13 }
    14 int dfn[N],low[N],dfn_cnt,scc_cnt,belong[N];
    15 stack<int>sta;
    16 void tarjan(int u){
    17     dfn[u]=low[u]=++dfn_cnt;
    18     sta.push(u);
    19     for(int i=Head[u];i;i=edge[i].next){
    20         int v=edge[i].to;
    21         if(!dfn[v]){
    22             tarjan(v);
    23             low[u]=min(low[u],low[v]);
    24         }
    25         else if(!belong[v]) low[u]=min(low[u],dfn[v]);
    26     }
    27     if(dfn[u]==low[u]){
    28         scc_cnt++;
    29         int t;
    30         do{
    31             t=sta.top();sta.pop();
    32             belong[t]=scc_cnt;
    33         }while(t!=u);
    34     }
    35 }
    36 int ru[N],chu[N];
    37 int main(){
    38     int n;
    39     scanf("%d",&n);
    40     for(int i=1;i<=n;++i){
    41         int x=1;
    42         scanf("%d",&x);
    43         while(x){
    44             Add(i,x);
    45             scanf("%d",&x);
    46         }
    47     }
    48     for(int i=1;i<=n;++i)
    49         if(!dfn[i]) tarjan(i);
    50     for(int i=1;i<=tot;++i){
    51         int x=edge[i].from,y=edge[i].to;
    52         if(belong[x]!=belong[y]){
    53             chu[belong[x]]++;ru[belong[y]]++;
    54         }
    55     }
    56     int ans1=0,ans2=0;
    57     if(scc_cnt==1){
    58         printf("1
    0
    ");
    59         return 0;
    60     }
    61     for(int i=1;i<=scc_cnt;++i){
    62         if(!ru[i]) ans1++;
    63         if(!chu[i]) ans2++;
    64     }
    65     printf("%d
    %d
    ",ans1,max(ans2,ans1));
    66     return 0;
    67 }
    P2746 [USACO5.3]校园网Network of Schools
     1 #include<bits/stdc++.h>
     2 #define lson (t<<1)
     3 #define rson (t<<1|1)
     4 #define mid ((l+r)>>1)
     5 using namespace std;
     6 const int N=1e6+10;
     7 struct Tree{
     8     int l,r,Max,lazy;
     9 }tree[N<<2];
    10 void pushup(int t){
    11     tree[t].Max=max(tree[lson].Max,tree[rson].Max);
    12 }
    13 void pushdown(int t){
    14     tree[lson].Max=max(tree[lson].Max,tree[t].lazy);
    15     tree[lson].lazy=max(tree[lson].lazy,tree[t].lazy);
    16     tree[rson].Max=max(tree[rson].Max,tree[t].lazy);
    17     tree[rson].lazy=max(tree[rson].lazy,tree[t].lazy);
    18     tree[t].lazy=0;
    19 }
    20 void change(int t,int l,int r,int cl,int cr,int num){
    21     if(cl>r || cr<l) return;
    22     if(cl<=l&&r<=cr){
    23         tree[t].lazy=max(tree[t].lazy,num);
    24         tree[t].Max=max(tree[t].Max,num);
    25         return;
    26     }
    27     pushdown(t);
    28     if(cr<=mid) change(lson,l,mid,cl,cr,num);
    29     else if(cl>mid) change(rson,mid+1,r,cl,cr,num);
    30     else{
    31         change(lson,l,mid,cl,cr,num);change(rson,mid+1,r,cl,cr,num);
    32     }
    33     pushup(t);
    34 }
    35 int query(int t,int l,int r,int ql,int qr){
    36     if(ql>r || qr<l) return 0;
    37     if(ql<=l&&r<=qr){
    38         return tree[t].Max;
    39     }
    40     pushdown(t);
    41     if(qr<=mid) return query(lson,l,mid,ql,qr);
    42     else if(ql>mid) return query(rson,mid+1,r,ql,qr);
    43     else return max(query(lson,l,mid,ql,qr),query(rson,mid+1,r,ql,qr));
    44 }
    45 struct Input{
    46     int x,h,y;
    47 }a[N];
    48 int n=0;
    49 int tot=0;
    50 int b[N];
    51 int main(){
    52     //freopen("a.in","r",stdin);
    53     int x,y,z;
    54     while(scanf("%d%d%d",&x,&y,&z)==3){
    55         a[++tot].x=x;a[tot].h=y;a[tot].y=z;
    56     }
    57     for(int i=1;i<=tot;++i){
    58         int x=a[i].x,y=a[i].y,h=a[i].h;
    59         change(1,1,10000,x,y-1,h);
    60     }
    61     for(int i=1;i<=10000;++i) b[i]=query(1,1,10000,i,i);
    62     for(int i=1;i<=10000;++i){
    63         //printf("%d %d
    ",i,b[i]);
    64         if(b[i]!=b[i-1])    
    65             printf("%d %d ",i,b[i]);
    66     }
    67     return 0;
    68 }
    P1904 天际线

    总结:

    今天一天还是挺顺心的,上午考试考了自己集训以来的最好成绩(虽然洛谷说今天大凶),然后今天下午也感觉学到了不少东西,和同学们一起刷了一些题,听说11号奥赛生都要回校(我们是不是回不了家了),这样就又能一起练习了,希望明天能够取得一个好成绩吧.

  • 相关阅读:
    java如何将char类型的数字转换成int型的数字,而不是Ascii
    java 二分查找的注意事项
    IntelliJ IDEA 下的svn配置及使用的非常详细的图文总结
    java中Math的常用方法整理
    判断字符串是否可由重复子字符串组成
    P3558 [POI2013]BAJ-Bytecomputer
    BZOJ 3329. Xorequ
    Codeforces 1221F. Choose a Square
    Codeforces 1221E. Game With String
    Codeforces 1221D. Make The Fence Great Again
  • 原文地址:https://www.cnblogs.com/li-jia-hao/p/13210357.html
Copyright © 2011-2022 走看看