完成度 (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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
Problem I
题目大意
题目分析
参考程序
Problem J
题目大意
题目分析
参考程序