暑假集训热身赛

时间:2022-02-09 10:20:50

 完成度 (8 / 10)

Problem A

题目大意

  给定 m,n,询问二元组(x,y)( 1 <= x <= m , 1 <= y <= n) 满足 ( x + y ) % 5 = 0 的组数。

解题分析

  直接枚举x与y的模余

参考程序

暑假集训热身赛暑假集训热身赛
 1 #include <cstdio>
 2 
 3 int m,n;
 4 int a[6],b[6];
 5 
 6 int main()
 7 {
 8     scanf("%d%d",&n,&m);
 9     for (int i=1;i<=5;i++) a[i]=(n-i+5) / 5 ;
10     for (int i=1;i<=5;i++) b[i]=(m-i+5) / 5 ; 
11  
12     long long ans=0;
13     for (int i=1;i<=4;i++) ans+=(long long)a[i]*b[5-i];
14     ans+=(long long)a[5]*b[5];
15     
16     printf("%I64d",ans);
17     return 0;
18 }
View Code

 

Problem B

题目大意

  给定一个序列,可以任意减小某个元素,使得最小不出现的自然数最大。

解题分析

  排序之后贪心扫一遍。

参考程序

暑假集训热身赛暑假集训热身赛
 1 #include <cstdio>
 2 #include <algorithm>
 3 using namespace std;
 4 
 5 #define maxn 100008
 6 int a[maxn];
 7 int n;
 8 
 9 int main()
10 {
11     scanf("%d",&n);
12     for (int i=1;i<=n;i++) scanf("%d",&a[i]);
13     sort(a+1,a+n+1);
14     //for (int i=1;i<=n;i++) printf("%d ",a[i]);
15     int ans=1;
16     for (int i=1;i<=n;i++)
17         if (a[i]>=ans) ans++;
18     printf("%d\n",ans);
19     return 0;
20 
21 }
View Code

 

Problem C

题目大意

  给一棵树,如果这个节点u与它的一个子节点v dist(u,v)>=a[u] 那么这个节点就是sad节点

  每次操作可以去掉一个叶子节点,问最少去掉多少个节点才能使这棵树没有sad节点;

解题分析

  dfs一遍,记录从根节点开始到该节点的最长路径,若大于某个节点,则去掉给节点及其子树。

参考程序

暑假集训热身赛暑假集训热身赛
 1 #include <cstdio>
 2 #include <algorithm>
 3 using namespace std;
 4 #define maxn 100008
 5 #define maxm 200008
 6 
 7 struct line
 8 {
 9     int u,v,nt;
10     long long w;
11 }eg[maxm];
12 
13 int v[maxn],lt[maxn],son[maxn];
14 int n,sum=1,ans=0;
15 
16 void add(int u,int v,int w)
17 {
18     eg[++sum].u=u; eg[sum].v=v; eg[sum].w=w; 
19     eg[sum].nt=lt[u]; lt[u]=sum;
20 }
21 
22 void dfs(int u,int fa,long long dist)
23 {
24     if (dist>v[u]) return;
25     son[u]=1;
26     for (int i=lt[u];i;i=eg[i].nt)
27         if (eg[i].v!=fa)
28         {
29             dfs(eg[i].v,u,max(0LL,dist+eg[i].w));
30             son[u]+=son[eg[i].v];
31         }
32 
33 }
34 
35 int main()
36 {
37     scanf("%d",&n);
38     for (int i=1;i<=n;i++) scanf("%d",&v[i]);
39 
40     int x,y;
41     for (int i=2;i<=n;i++)
42     {
43         scanf("%d%d",&x,&y);
44         add(i,x,y);
45         add(x,i,y);
46     }
47 
48     dfs(1,0,0);
49 
50     printf("%d\n",n-son[1]);
51     return 0;
52 }
View Code

 

Problem D

题目大意

  给定两个长度均小于等于1000的字符串S,T,在S串中找k个连续的子串,并且这些字串在T串中均出现且顺序相同,问这些字串最大的长度和。

解题分析

  最长公共子序列的拓展。

  令f[i,j] 表示S串第i位 T串第j位 往前最多几位相同

  dp[i,j,k] 表示匹配到S串第i位 T串第j位 k个序列的最长匹配长度

  那么dp[i,j,k]=max{ dp[i-f[i,j]][j-f[i,j]][k-1]+f[i,j],dp[i-1,j,k] , dp[i,j-1,k] }

参考程序

暑假集训热身赛暑假集训热身赛
 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 using namespace std;
 5 
 6 #define maxn 1008
 7 #define maxk 15
 8 
 9 char s[maxn],t[maxn];
10 int f[maxn][maxn],dp[maxn][maxn][maxk];
11 
12 int n,m,len;
13 int max(int a,int b,int c){
14     if (a>=b && a>=c) return a;
15     if (b>=a && b>=c) return b;
16     if (c>=a && c>=b) return c;
17 }
18 int main(){
19     scanf("%d%d%d",&m,&n,&len);
20     scanf("%s",s+1);
21     scanf("%s",t+1);
22 
23     for (int i = 1;i <= m;i++)
24         for (int j = 1;j <= n;j++)
25             if (s[i] == t[j]) 
26                 f[i][j] = f[i - 1][j -1 ] + 1;
27             else f[i][j] = 0;
28 
29     for (int k = 1;k <= len;k++)
30         for (int i = 1;i <= m;i++)
31             for (int j = 1;j <= n ; j ++)
32                 dp[i][j][k] =max(dp[i - f[i][j]][j - f[i][j]][k - 1] + f[i][j] , dp[i - 1][j][k] , dp[i][j - 1][k]);
33                 
34     printf("%d\n",dp[m][n][len]);
35 
36 }
View Code

 

Problem E

题目大意

题目分析

参考程序

暑假集训热身赛暑假集训热身赛
 1 #include <cstdio>
 2 #include <cstring>
 3 using namespace std;
 4 
 5 int n;
 6 char s[20];
 7 int x[]={4,1,1,1,2,2,2,3,3,3};
 8 int y[]={2,1,2,3,1,2,3,1,2,3};
 9 int ok[20][20];
10 bool pd;
11 
12 int main()
13 {
14     memset(ok,0,sizeof(ok));
15     for (int i=0;i<=9;i++)
16         ok[x[i]+5][y[i]+5]=1;
17 
18     scanf("%d%s",&n,s+1);
19 
20     pd=false;
21     int i,j;
22     for (i=0;i<=9;i++) if (i!=s[1]-'0')
23     {
24         int tx=x[i];
25         int ty=y[i];
26         for (j=2;j<=n;j++)
27         {    
28             tx+=x[s[j]-'0']-x[s[j-1]-'0'];
29             ty+=y[s[j]-'0']-y[s[j-1]-'0'];
30             if (!ok[tx+5][ty+5]) break;
31         }
32         if (j==n+1) pd=true;
33     }
34     if (pd==true) printf("NO"); else printf("YES");
35 
36 }
View Code

 

Problem F

题目大意

题目分析

参考程序

暑假集训热身赛暑假集训热身赛
 1 #include <cstdio>
 2 #include <queue>
 3 #include <cstring>
 4 using namespace std;
 5 
 6 #define maxn 200008
 7 #define INF 1000000000;
 8  
 9 int n;
10 int dist[maxn],pd[maxn];
11 
12 
13 struct line{
14     int u,v,w,nt;
15 }eg[maxn*4];
16 int lt[maxn],sum = 1;
17 void adt(int u,int v,int w){
18     eg[++sum].u = u; eg[sum].v = v; eg[sum].w = w; eg[sum].nt = lt[u]; lt[u] = sum;
19 }
20 void add(int u,int v,int w){
21     adt(u,v,w);
22     adt(v,u,w);
23 }
24 
25 void spfa(){
26     memset(pd,0,sizeof(pd));
27     for (int i = 1;i <= n;i++) dist[i]=INF;
28     queue<int> Q;
29     dist[1] = 0; Q.push(1); pd[1] = 1;
30     while (!Q.empty()){
31         int u = Q.front();
32         for (int i = lt[u];i;i = eg[i].nt){
33             int v = eg[i].v;
34             if (dist[u] + eg[i].w < dist[v]){
35                 dist[v] = dist[u] + eg[i].w;
36                 if (!pd[v]){
37                     Q.push(v);
38                     pd[v] = 1;
39                 }
40             }
41         }
42         Q.pop();
43         pd[u]=0;
44     }
45     for (int i=1;i<=n;i++) printf("%d ",dist[i]);
46     printf("\n");
47 }
48 
49 int main(){
50     memset(lt,0,sizeof(lt));
51     scanf("%d",&n);
52     for (int i = 1;i <= n;i++){
53         int j;
54         scanf("%d",&j);
55         if (i != n) add(i,i+1,1);
56         adt(i,j,1);
57     }
58     spfa();
59 }
View Code

 

Problem G

题目大意

题目分析

参考程序

暑假集训热身赛暑假集训热身赛
 1 #include <cstdio>
 2 
 3 long long m;
 4 
 5 long long check(long long x){
 6     long long sum=0;
 7     for (long long i = 2;i * i * i <= x;i++)
 8         sum += x / (i * i * i);    
 9     return sum;
10 }
11 
12 int main(){
13     scanf("%I64d",&m);
14     long long l = 1,r = 1e16,mid,res = -1;
15     while (l <= r){
16         mid = (l + r) /2;
17         if (check(mid) >= m){
18             res = mid;
19             r = mid - 1;
20         }
21         else l = mid + 1; 
22     }
23     if (check(res) == m) printf("%I64d\n",res); else printf("-1");
24 }
View Code

 

Problem H

题目大意

题目分析

参考程序

暑假集训热身赛暑假集训热身赛
 1 #include <cstdio>
 2 #include <algorithm>
 3 using namespace std;
 4 
 5 #define maxn 200008
 6 #define len 20
 7 int n;
 8 int a[maxn],b[maxn];
 9 int fa[maxn][len],fb[maxn][len];
10 
11 void rmq_inita(){
12     for (int i = 1; i <= n;i++)
13         fa[i][0] = a[i];
14     for (int j = 1; (1 << j) <= n;j++)
15         for (int i = 1;i + (1 << j) - 1 <= n;i++)
16             fa[i][j] = max(fa[i][j - 1] , fa[i + (1 << j - 1)][j - 1]);
17 }
18 
19 int rmqa(int l,int r){
20     int k = 0;
21     while (1 << (k+1) <= r - l + 1) k++;
22     return max(fa[l][k] , fa[r - (1 << k) + 1][k]);
23 }
24 
25 
26 void rmq_initb(){
27     for (int i = 1; i <= n;i++)
28         fb[i][0] = b[i];
29     for (int j = 1; (1 << j) <= n;j++)
30         for (int i = 1;i + (1 << j) - 1 <= n;i++)
31             fb[i][j] = min(fb[i][j - 1] , fb[i + (1 << j - 1)][j - 1]);
32 }
33 
34 int rmqb(int l,int r){
35     int k = 0;
36     while (1 << (k+1) <= r - l + 1) k++;
37     return min(fb[l][k] , fb[r - (1 << k) + 1][k]);
38 }
39 
40 int main(){
41     scanf("%d",&n);
42     for (int i = 1;i <= n;i++) scanf("%d",&a[i]);
43     for (int i = 1;i <= n;i++) scanf("%d",&b[i]);
44     rmq_inita();
45     rmq_initb();
46     int L;
47     long long ans=0;
48     for (L = 1;L <= n;L++){
49         int l,r,mid,res1=0,res2=0;
50         l = L; r = n ;
51         while (l <= r){
52             mid = (l + r) / 2;
53             if (rmqb(L,mid) - rmqa(L,mid) >= 0){
54                 res1 = mid;
55                 l = mid + 1;
56             } 
57             else     
58                 r = mid - 1;
59         }
60 
61         l = L; r = n ;
62         while (l <= r){
63             mid = (l + r) / 2;
64             if (rmqa(L,mid) - rmqb(L,mid) >= 0){
65                 res2 = mid;
66                 r = mid - 1;
67             } 
68             else     
69                 l = mid + 1;
70         }
71         if (rmqa(L,res1) == rmqb(L,res1) && rmqa(L,res2) == rmqb(L,res2) )ans += res1 - res2 +1;
72     }
73     printf("%I64d\n",ans);
74     return 0;
75 }
View Code

 

Problem I

题目大意

题目分析

参考程序

 

Problem J

题目大意

题目分析

参考程序