【寒假集训系列DAY.1】

Problem A. String Master(master.c/cpp/pas)

题目描述

 所谓最长公共子串,比如串 A:“abcde”,串 B:“jcdkl”,则它们的最长公共子串为串 “cd”,即长
度最长的字符串,且在两个串中都作为连续子串出现过。
给定两个长度都为 n 的字符串,对于字符串大师的你来说,求它们的最长公共子串再简单不过了。
所以现在你有 k 次修改机会,每次你可以选择其中某个串的某个位置,将其修改成任意字符。
你需要合理使用这 k 次修改机会,使得修改之后两个串的最长公共子串最长。相信对于字符串大师
的你来说,这个问题也难不倒你。
Input
第一行包含两个整数 n, k,分别表示字符串的长度和修改次数。
第二行包含一个长度为 n 的仅由小写字符构成的字符串 S。
第三行包含一个长度为 n 的仅由小写字符构成的字符串 T。
Output
输出一行一个整数,即修改完毕之后两个串的最长公共子串的长度。

k<=n<=300

题目大意:两个字符串,任意改动k个字母,使得最长公共子串最长

思路:两个指针i,j,代表从S串第i个位置开始,T串从第j个位置开始,枚举长度len,求出在两边找出的子串在k次修改机会内的最大长度

复杂度:O(N^3)

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 using namespace std;
 6 inline int read(){
 7     char chr=getchar();    int f=1,ans=0;
 8     while(!isdigit(chr)) {if(chr==‘-‘) f=-1;chr=getchar();}
 9     while(isdigit(chr))  {ans=(ans<<3)+(ans<<1);ans+=chr-‘0‘;chr=getchar();}
10     return ans*f;
11 }
12 void write(int x){
13     if(x<0) putchar(‘-‘),x=-x;
14     if(x>9) write(x/10);
15     putchar(x%10+‘0‘);
16 }
17 const int N=301;
18 char S[N],T[N],tS[N],tT[N];
19 int n,k,f[N][N];
20 inline int Check(char *S,char *T){
21     int ans=0;
22     for(int i=1;i<=n;i++)
23         for(int j=1;j<=n;j++){
24             int cs=0,len;
25             for(len=1;len<=min(n-i+1,n-j+1);len++){
26                 if(S[i+len-1]!=T[j+len-1])
27                     if(cs>=k) break;
28                     else cs++;
29             }ans=max(ans,len-1);
30         }return ans;
31
32 }
33 int main(){
34     freopen("master.in","r",stdin);
35     freopen("master.out","w",stdout);
36     n=read(),k=read();
37     scanf("%s",S+1);scanf("%s",T+1);
38     write(Check(S,T));
39     return 0;
40 }

Problem B. Tourist Attractions(tour.c/cpp/pas)

题目描述

 在美丽的比特镇一共有 n 个景区,编号依次为 1 到 n,它们之间通过若干条双向道路连接。
Byteasar 慕名来到了比特镇旅游,不过由于昂贵的门票费,他只能负担起 4 个景区的门票费。他可
以在任意景区开始游览,然后结束在任意景区。
Byteasar 的旅游习惯比较特殊,一旦他路过了一个景区,他就一定会进去参观,并且他永远不会参
观同一个景区两次。所以他想知道,有多少种可行的旅游路线,使得他可以恰好参观 4 个景区呢?即,
有多少条简单路径恰好经过了 4 个点。
Input
第一行包含两个整数 n,表示景区的总数。
第 2 至第 n + 1 行,每行一个长度为 n 的 01 字符串,第 i + 1 行第 j 个字符为 0 表示 i 和 j 之间
没有道路,为 1 表示有一条道路。
输入数据保证 (i, j) 的连接情况等于 (j, i) 的连接情况,且 (i, i) 恒为 0。
Output
输出一行一个整数,即可行的路线总数。

n<=1500

记得开long long!!!        记得开long long!!!         记得开long long!!!

40pts(直接枚举第一二三四个点,判断是否重复,是否按顺序连通——O(n^4))

70pts(枚举其中的第一二三个点,第四个点个数就是第三个点的度数-1,当然考虑环的情况,如果第三个点和第一个点连通,要再1   要开long long 比赛的时候因为这个丢掉30分) ——O(n^3)

100ptsbitset优化,对于每个类似于a-b-c-d的四元组我们枚举中间的俩元素b-c
    然后对于这一组元素对答案的贡献为(du[b]-1)*(du[c]-1)-包含b-c这组元素的三元环个数
   枚举三元环的个数 ,其中两个元素b-c已经确定,只要再找一个元素x同时满足x-b连通 且x-c连通即可
   然而找到元素x最简单的方法即O(n) 枚举,但是这样的话时间复杂度重新退化为O(n^3)
   于是考虑bitset优化, 假设与b相连的元素集合为s[b],
   则三元环个数即为(s[b]&s[c]).count()(两集合并集中1的个数,即同时与b,c相连)——O(n^3/32)

    本题对于Pascal选手还是不太友好的,但手动bitset也不是不可以/滑稽

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<bitset>
 6 #define int long long //懒人专用
 7 using namespace std;
 8 inline int read(){
 9     char chr=getchar();    int f=1,ans=0;
10     while(!isdigit(chr)) {if(chr==‘-‘) f=-1;chr=getchar();}
11     while(isdigit(chr))  {ans=(ans<<3)+(ans<<1);ans+=chr-‘0‘;chr=getchar();}
12     return ans*f;
13 }
14 void write(int x){
15     if(x<0) putchar(‘-‘),x=-x;
16     if(x>9) write(x/10);
17     putchar(x%10+‘0‘);
18 }
19 int n,a[1505][1505],du[1505];
20 char s[1505];
21 long long ans=0;
22 bitset<1505> ss[1505];
23 signed main(){
24     freopen("tour.in","r",stdin);
25     freopen("tour.out","w",stdout);
26     n=read();
27     for(register int i=1;i<=n;++i){
28         scanf("%s",s+1);
29         for(register int j=1;j<=n;++j)
30             if(s[j]==‘0‘) a[i][j]=0;else a[i][j]=1,du[i]++;
31     }
32     if(n<=50)//①40pts,这里码风可能不太友好(考试的时候为了卡常)当然了,如果100分方法看懂了可以略过前两种部分分的方法
33     for(register int i=1;i<=n;++i)
34         for(register int j=1;j<=n;++j){if(i!=j&&a[i][j])
35             for(register int k=1;k<=n;++k){if(j!=k&&i!=k&&a[j][k])
36                 for(register int l=1;l<=n;++l){if(i!=l&&j!=l&&k!=l&&a[k][l])++ans;}}}
37     else if(n<=300){
38 //②70pts
39         for(register int i=1;i<=n;++i)
40             for(register int j=1;j<=n;++j){
41                 if(i==j) continue;
42                 if(!a[i][j]) continue;
43                 for(register int k=1;k<=n;++k){
44                     if(i==k||j==k) continue;
45                     if(!a[j][k]) continue;
46                     ans+=du[k]-1;
47                     if(a[k][i]) ans--;
48                 }
49             }
50     }else{
51 //③100pts
52         for(int i=1;i<=n;i++)
53             for(int j=1;j<=n;j++)
54                 if(a[i][j]==0) ss[i][j]=0;else ss[i][j]=1;
55         for(int i=1;i<=n;i++)
56             for(int j=1;j<=n;j++){
57                 if(!a[i][j]) continue;
58                 if(i==j) continue;
59                 ans+=(du[i]-1)*(du[j]-1)-(ss[i]&ss[j]).count();
60             }
61     }
62     write(ans);
63     return 0;
64 }

Problem C. Walk(walk.c/cpp/pas)

考试妥妥的打暴力系列

在比特镇一共有 n 个街区,编号依次为 1 到 n,它们之间通过若干条单向道路连接。
比特镇的交通系统极具特色,除了 m 条单向道路之外,每个街区还有一个编码 vali,不同街区可能
拥有相同的编码。如果 vali and valj = valj,即 vali 在二进制下与 valj 做与运算等于 valj,那么也会
存在一条额外的从 i 出发到 j 的单向道路。
Byteasar 现在位于 1 号街区,他想知道通过这些道路到达每一个街区最少需要多少时间。因为比特
镇的交通十分发达,你可以认为通过每条道路都只需要 1 单位时间。
Input
第一行包含两个正整数 n, m,表示街区的总数以及道路的总数。
第二行包含 n 个正整数 val1, val2, ..., valn,分别表示每个街区的编码。
接下来 m 行,每行包含两个正整数 ui
, vi,表示一条单向道路,起点为 ui,终点为 vi。
Output
输出 n 行,每行一个整数,其中第 i 行输出到达第 i 个街区的最少时间,如果无法到达则输出 −1

①20分,直接求就好了

②40分,O(n^2)建图,O(n)BFS求最短路

③70分,考虑重新构图,新增1<<15个点,枚举子集(O(n^3)),向点 i 向它所有的子集连一条权值为 0 的有向边,然后在向原图中连回去,可能表达不太对,画个图意会一下//待会儿FFT来说又怪语文老师

④100分,还是新建图,点i 只需要向点 i 去掉某一位的 1 的点连边,这样边的数量得到有效控制

 1 #pragma GCC optimize(2)
 2 #include<iostream>
 3 #include<cstdio>
 4 #include<cstring>
 5 #include<algorithm>
 6 #include<queue>
 7 #define ll long long
 8 using namespace std;
 9 inline int read(){
10     char chr=getchar();    int f=1,ans=0;
11     while(!isdigit(chr)) {if(chr==‘-‘) f=-1;chr=getchar();}
12     while(isdigit(chr))  {ans=(ans<<3)+(ans<<1);ans+=chr-‘0‘;chr=getchar();}
13     return ans*f;
14 }
15 void write(int x){
16     if(x<0) putchar(‘-‘),x=-x;
17     if(x>9) write(x/10);
18     putchar(x%10+‘0‘);
19 }
20 const int N=1300005;
21 int val[N],cnt;
22 int n,m,ver[N<<1],head0[N<<1],head1[N<<1],nxt[N<<1],dis[N<<1],tot=0,x,y,hd=1,tl=0,q[N];
23 bool vis[N<<1];
24 inline void add1(int x,int y){ver[++tot]=y;nxt[tot]=head1[x];head1[x]=tot;}
25 inline void add0(int x,int y){ver[++tot]=y;nxt[tot]=head0[x];head0[x]=tot;}
26 void Run(int x,int w){
27   if(dis[x]>=0)return;
28   dis[q[++tl]=x]=w;
29   for(int i=head0[x];i;i=nxt[i])     Run(ver[i],w);
30   if(x>=cnt) return;
31   for(int i=0;i<20;i++)if(x>>i&1)    Run(x^(1<<i),w);
32 }
33 int main(){
34     freopen("walk.in","r",stdin);
35     freopen("walk.out","w",stdout);
36     n=read(),m=read();cnt=1<<20;
37     for(int i=1;i<=n;i++)    x=read(),add1(i+cnt,x),add0(x,i+cnt);
38     for(int i=1;i<=m;i++)   x=read(),y=read(),add1(x+cnt,y+cnt);
39     for(int i=1;i<=n+cnt;i++) dis[i]=-1;
40     Run(cnt+1,0);
41     while(hd<=tl)for(int i=head1[x=q[hd++]];i;i=nxt[i])Run(ver[i],dis[x]+1);
42     for(int i=1;i<=n;i++) write(dis[i+cnt]),puts("");
43     return 0;
44 }

原文地址:https://www.cnblogs.com/zhenglw/p/10326669.html

时间: 2024-11-02 10:13:45

【寒假集训系列DAY.1】的相关文章

【寒假集训系列DAY3】

DAY2的坑之后会补上 DAY3 今天暴力分拿的还是不错的...60+30+25=115,但还是太弱了呀,每题都只会暴力(话说第3题直接输-1给了15分,本以为只会给5分,然后打了半个小时的爆搜...) T1:Simple (图样图森破) [问题描述] 对于给定正整数 n,m,我们称正整数 c 为好的,当且仅当存在非负整数 x,y,使得 n*x+m*y=c.现在给出多组数据,对于每组数据,给定 n,m,q,求[1,q]内有多少个正整数不是好的.[输入格式] 第一行,一个整数 T 表示数据组数.接

CSU-ACM寒假集训选拔-入门题

CSU-ACM寒假集训选拔-入门题 仅选择部分有价值的题 J(2165): 时间旅行 Description 假设 Bobo 位于时间轴(数轴)上 t0 点,他要使用时间机器回到区间 (0,?h] 中. 当 Bobo 位于时间轴上 t 点,同时时间机器有 c 单位燃料时,他可以选择一个满足 \(\lceil\frac{x}{h}\rceil\leq c\) 的非负整数 x, 那么时间机器会在 [0,?x]中随机整数 y,使 Bobo 回到 (t???y) 点,同时消耗 y 单位燃料. (其中 ?

寒假集训总结

这个寒假的集训吧,缺少了总结. 首先去了秦皇岛的几天还是挺不错的,但是人还是很懒散,没有每日做总结,导致以前会做的题目不会做.COME OJ上的视频也没有看完.秦皇岛开阔了眼界吧. 放寒假前的几天吧,都在聊天,唉,真的有时候会感到孤独... 只写了两场CF的所有题题解对的.(还缺178场) 之后回学校吧一个人在寝室就看看游戏直播的视频,嗯,挺荒废的. 寒假的收货吧,会了时间线段树,一些些STL,dp做了总结,分块+暴力的方法. 之后应该干什么呢,3月17校赛,3月底天梯,4月初浙大校赛,4月底浙

高一寒假集训总结

集训的一天 早读改前一天晚上没过的题. 上午学新课,开新的一套题,学模版优化模版.前半段总是没睡醒,将近中午时效率是一天中最高的.一般不大讨论. 下午继续做题,效率也比较高.讨论比上午多. 晚上思路很乱,而且一般都是做到一套题的后几道,进程缓慢,有些错误往往要到第二天早上才能想通. 集训之最 最有感触的一道题:家谱树.为了存人名现学关联式容器,发现大家课下确实学了不少东西,开学之后要拿更多时间读奥赛书,自学一些内容. 最佩服的一种解法:王超星的挖水井.这道题我做了很久,还是没能解决.请教王超星的

寒假集训日志(二)——最小生成树,拓扑排序,欧拉回路,连通路

今天学的内容挺多的. (一)首先说最小生成树,两种算法: 1.Kruskal算法( 将边排序,然后再选,关键在于检查是否连通,使用并查集) 2.Prim算法(使用点集,有点类似与最短路的算法) 第一题是并查集算法的使用: A - The Suspects Time Limit:1000MS     Memory Limit:20000KB     64bit IO Format:%I64d & %I64u Submit Status Description 严重急性呼吸系统综合症( SARS),

(寒假集训)Roadblock(最短路)

Roadblock 时间限制: 1 Sec  内存限制: 64 MB提交: 9  解决: 5[提交][状态][讨论版] 题目描述 Every morning, FJ wakes up and walks across the farm from his house to the barn.  The farm is a collection of N fields (1 <= N <= 250) connected by M bidirectional pathways (1 <= M

(寒假集训)Mooo Moo (完全背包)

Mooo Moo 时间限制: 1 Sec  内存限制: 64 MB提交: 5  解决: 4[提交][状态][讨论版] 题目描述 Farmer John has completely forgotten how many cows he owns!  He is too embarrassed to go to his fields to count the cows, since he doesn't want the cows to realize his mental lapse.  Ins

(寒假集训)Watering the Fields (最小生成树)

Watering the Fields 时间限制: 1 Sec  内存限制: 64 MB提交: 26  解决: 10[提交][状态][讨论版] 题目描述 Due to a lack of rain, Farmer John wants to build an irrigation system to send water between his N fields (1 <= N <= 2000). Each field i is described by a distinct point (x

(寒假集训) 卡片(离散化)

卡片 时间限制: 1 Sec  内存限制: 128 MB提交: 22  解决: 13[提交][状态][讨论版] 题目描述 每个卡片的开头和结尾都有标记,把每张卡片看成数轴上的一条线段,开头和结尾的标记A,B为数轴上的两个点.每张卡片的颜色都不同.将卡片按照标记贴到数轴上,请问贴完卡片以后的数轴上一共有多少种不同的颜色. 输入 第1行:一个整数N,表示卡片的数量. 第2行至第N+1行:第i+1行给出了第i张卡片的头尾两个标记Ai,Bi,贴卡片的顺序与输入文件中出现的先后顺序一致. 输出 一个整数,