码迷,mamicode.com
首页 > 其他好文 > 详细

【SRM-08】解题报告

时间:2017-07-28 00:57:07      阅读:230      评论:0      收藏:0      [点我收藏+]

标签:first   信息   printf   alt   getchar   min   表示   bit   一个   

A

Description

给一个 01 串设为其 S,询问是否存在只出现两次的 01 串 T。

这里的出现定义为存在一串下标 技术分享,满足 技术分享 且 技术分享

Input

一行,一个 01 串

Output

一行,字母 Y 表示存在,N 表示不存在

HINT

1.设串 S 的长度为 n,技术分享

2.设串 S 的长度为 n,技术分享

3.设串 S 的长度为 n,技术分享

4.数据为随机生成。

 

对于第一部分,打个表骗分。

技术分享
 1 #include<cstdio>
 2 #include<algorithm> 
 3 #include<cstring>
 4 using namespace std;
 5 char s[5],num0,num1;
 6 int main()
 7 {
 8     scanf("%s",s);
 9     int len=strlen(s);
10     for(int i=0;i<len;i++)
11         if(s[i]==0)num0++;
12         else num1++;
13     if((num0%2&&num1%2)||num0==3||num1==3)printf("N");
14     else printf("Y");
15     return 0;
16 }
View Code

对于第二部分,暴力dfs。

技术分享
 1 #include<cstdio>
 2 #include<algorithm> 
 3 #include<cstring>
 4 using namespace std;
 5 const int N=1<<12;
 6 int n,a[15],calc[15][N];
 7 char s[15];
 8 bool f;
 9 int read()
10 {
11     int x=0,f=1;char c=getchar();
12     while(c<0||c>9){if(x==-)f=-1;c=getchar();}
13     while(c>=0&&c<=9){x=x*10+c-0;c=getchar();}
14     return x*f;
15 }
16 void dfs(int x,int sum,int num,int k)
17 {
18     sum=sum*2+a[x];
19     if(a[x]||k)k=1;
20     else num++;
21     calc[num][sum]++;
22     for(int i=x+1;i<=n;i++)dfs(i,sum,num,k);
23 }
24 int main()
25 {
26     scanf("%s",s);
27     n=strlen(s);
28     for(int i=0;i<n;i++)a[i+1]=s[i]-0;
29     for(int i=1;i<=n;i++)dfs(i,0,0,0);
30     int summ=1<<n;
31     for(int i=0;i<=n;i++)
32         for(int j=0;j<summ;j++)
33             if(calc[i][j]==2){f=true;break;}
34     if(f)printf("Y");
35     else printf("N");
36     return 0;
37 }
View Code

对于第三部分,注意特判0和1的个数恰好为2的情况。

对于其他情况,若存在形如abcd(a!=b,b==c,c!=d)(即0110或1001)类型的子串,则输出Y。此时T为 b前面的所有数字+b(也是c)+后面的所有数字。

技术分享
 1 #include<cstdio>
 2 #include<algorithm> 
 3 #include<cstring>
 4 using namespace std;
 5 int n,zero;
 6 char s[5010];
 7 bool f;
 8 int main()
 9 {
10     scanf("%s",s+1);
11     n=strlen(s+1);
12     for(int i=1;i<=n;i++)
13         if(s[i]==0)zero++;
14     if(zero==2||n-zero==2)f=true;
15     for(int i=0;i<n-1;i++)
16         if(s[i]!=s[i+1]&&s[i+1]==s[i+2]&&s[i+2]!=s[i+3])f=true;
17     if(f)printf("Y");
18     else printf("N");
19     return 0;
20 }
View Code

 

B

Description

给长度为 n 的数列 A 和长度为 m 的数列 B,问有多少长度为 m 的数列 C 满足

技术分享技术分享

Input

第一行俩整数 n 和 m

第二行 n 个整数 技术分享,表示数列 A

第三行 m 个整数 技术分享,表示数列 B

Output

一个整数,表示满足条件的数列 C 的个数模 技术分享 后的值。

HINT

1.技术分享    技术分享    技术分享

2.技术分享    技术分享    技术分享

3.技术分享    技术分享    技术分享

 

对于第一部分,暴力dfs。(不要问我为什么不写dp

技术分享
 1 #include<cstdio>
 2 #include<algorithm> 
 3 #include<cstring>
 4 using namespace std;
 5 int n,m,ans,a[55],b[10];
 6 int read()
 7 {
 8     int x=0,f=1;char c=getchar();
 9     while(c<0||c>9){if(x==-)f=-1;c=getchar();}
10     while(c>=0&&c<=9){x=x*10+c-0;c=getchar();}
11     return x*f;
12 }
13 void dfs(int x,int deep)
14 {
15     if(m-deep>n-x)return;
16     if(deep==m){ans++;return;}
17     for(int i=x+1;i<=n;i++)
18         if(a[i]-a[x]+b[deep]>=0)dfs(i,deep+1);
19 }
20 int main()
21 {
22     n=read();m=read();
23     for(int i=1;i<=n;i++)a[i]=read();
24     for(int i=1;i<=m;i++)b[i]=read();
25     if(m==1){printf("%d",n);return 0;}
26     for(int i=1;i<m;i++)b[i]=b[i+1]-b[i];
27     for(int i=1;i<=n;i++)dfs(i,1);
28     printf("%d",ans);
29     return 0;
30 }
View Code

对于第二、三部分,dp+树状数组。

技术分享
 1 #include<cstdio>
 2 #include<algorithm> 
 3 #include<cstring>
 4 using namespace std;
 5 const int N=2010;
 6 const int mod=1e9+7;
 7 int n,m,cnt,ans;
 8 int b[N],id[N],num[N],t[N],f[N],g[N];
 9 struct node{int w,pos;}a[N];
10 int read()
11 {
12     int x=0,f=1;char c=getchar();
13     while(c<0||c>9){if(x==-)f=-1;c=getchar();}
14     while(c>=0&&c<=9){x=x*10+c-0;c=getchar();}
15     return x*f;
16 }
17 bool cmp(node a,node b){return a.w<b.w;}
18 int lowbit(int x){return x&-x;}
19 void insert(int x,int v)
20 {
21     while(x<=n)
22     {
23         t[x]=(t[x]+v)%mod;
24         x+=lowbit(x);
25     }
26 }
27 int query(int x)
28 {
29     int ans=0;
30     while(x)
31     {
32         ans=(ans+t[x])%mod;
33         x-=lowbit(x);
34     }
35     return ans;
36 }
37 int main()
38 {
39     n=read();m=read();
40     for(int i=1;i<=n;i++)
41         a[i].w=read(),a[i].pos=i,f[i]=1;
42     sort(a+1,a+n+1,cmp);
43     for(int i=1;i<=n;i++)
44         if(a[i].w==a[i-1].w)id[a[i].pos]=cnt;
45         else id[a[i].pos]=++cnt,num[cnt]=a[i].w;
46     for(int i=1;i<=m;i++)b[i]=read();
47     for(int i=2;i<=m;i++)
48     {
49         for(int j=1;j<=cnt;j++)
50         {
51             int u=g[j-1];
52             while(u<cnt&&num[u+1]+b[i-1]<=num[j]+b[i])u++;
53             g[j]=u;
54         }
55         memset(t,0,sizeof(t));
56         insert(id[i-1],f[i-1]);
57         for(int j=i;j<=n;j++)
58         {
59             int sum=f[j];
60             f[j]=query(g[id[j]]);
61             insert(id[j],sum);
62         }
63     }
64     for(int i=m;i<=n;i++)ans=(ans+f[i])%mod;
65     printf("%d",ans);
66     return 0;
67 }
View Code

 

C

Description

给一个图,n 个点 m 条双向边,每条边有其长度。n 个点中有 k 个是特殊点,问任意两个特殊点的最短路是多少。

Input

第一行三个整数 n m k

第二行 k 个整数 技术分享,为各个特殊点

接下来 m 行,每行三个整数 x y d,表示 x 到 y 有一条长度为 d 的边

Output

一个整数

HINT

1.技术分享    技术分享    技术分享    技术分享    技术分享

2.技术分享    技术分享    技术分享    技术分享    技术分享

3.技术分享    技术分享    技术分享    技术分享    技术分享

4.图为联通图

 

对于第一部分,Floyd水过。(注意重边和自环)

技术分享
 1 #include<cstdio>
 2 #include<algorithm> 
 3 #include<cstring>
 4 using namespace std;
 5 const int inf=0x3f3f3f3f;
 6 int n,m,k,x,y,d,t,ans=inf;
 7 int dis[305][305];
 8 bool f[305];
 9 int read()
10 {
11     int x=0,f=1;char c=getchar();
12     while(c<0||c>9){if(x==-)f=-1;c=getchar();}
13     while(c>=0&&c<=9){x=x*10+c-0;c=getchar();}
14     return x*f;
15 }
16 int main()
17 {
18     n=read();m=read();k=read();
19     for(int i=1;i<=k;i++)
20     {
21         t=read();
22         f[t]=true;
23     }
24     for(int i=1;i<=n;i++)
25         for(int j=1;j<=n;j++)
26             if(i!=j)dis[i][j]=inf;
27     for(int i=1;i<=m;i++)
28     {
29         x=read();y=read();d=read();
30         dis[x][y]=dis[y][x]=min(dis[x][y],d);
31         if(f[x]&&f[y]&&x!=y)ans=min(ans,dis[x][y]);
32     }
33     for(int k=1;k<=n;k++)
34         for(int i=1;i<=n;i++)
35             for(int j=1;j<=n;j++)
36                 if(dis[i][j]>dis[i][k]+dis[k][j] )   
37                  {
38                      dis[i][j]=dis[i][k]+dis[k][j];
39                      if(f[i]&&f[j])ans=min(ans,dis[i][j]);
40                  }
41     printf("%d",ans);
42     return 0;
43 }
View Code

对于第二部分,跑k次SPFA。

技术分享
 1 #include<cstdio>
 2 #include<algorithm> 
 3 #include<cstring>
 4 using namespace std;
 5 const int N=100010;
 6 const int inf=0x3f3f3f3f;
 7 int n,m,k,x,y,t,cnt,ans=inf;
 8 int first[N],a[N],dis[N],q[N];
 9 bool f[N],in[N];
10 struct edge{int next,to,w;}e[N*2];
11 int read()
12 {
13     int x=0,f=1;char c=getchar();
14     while(c<0||c>9){if(x==-)f=-1;c=getchar();}
15     while(c>=0&&c<=9){x=x*10+c-0;c=getchar();}
16     return x*f;
17 }
18 void ins(int x,int y,int w){cnt++;e[cnt].to=y;e[cnt].w=w;e[cnt].next=first[x];first[x]=cnt;}
19 void spfa(int S)
20 {
21     memset(in,0,sizeof(in));
22     memset(dis,0x3f,sizeof(dis));
23     int head=0,tail=1;
24     q[0]=S;in[S]=true;dis[S]=0;
25     while(head!=tail)
26     {
27         int u=q[head++];in[u]=false;
28         if(head>100000)head=0;
29         for(int i=first[u];i;i=e[i].next)
30         {
31             int v=e[i].to;
32             if(dis[u]+e[i].w<dis[v])
33             {
34                 dis[v]=dis[u]+e[i].w;
35                 if(f[v])ans=min(ans,dis[v]);
36                 if(!in[v]){q[tail++]=v;in[v]=true;if(tail>100000)tail=0;}
37             }
38         }
39     }
40 }
41 int main()
42 {
43     n=read();m=read();k=read();
44     for(int i=1;i<=k;i++)a[i]=read(),f[a[i]]=true;
45     for(int i=1;i<=m;i++)
46     {
47         x=read();y=read();t=read();
48         ins(x,y,t);ins(y,x,t);
49     }
50     for(int i=1;i<=k;i++)spfa(a[i]);
51     printf("%d",ans);
52     return 0;
53 }
View Code

对于第三部分,对于每个点,维护以下信息:离它最近的特殊点及路程,离它次近的特殊点及路程(且需保证两个特殊点不同)。最后再扫一遍,用最短路+次短路来更新答案。

技术分享
 1 #include<cstdio>
 2 #include<algorithm> 
 3 #include<cstring>
 4 #include<queue>
 5 using namespace std;
 6 const int N=100010;
 7 const int inf=0x3f3f3f3f;
 8 int n,m,k,cnt,x,y,w,ans=inf;
 9 int a[10010],first[N],fir[N],sec[N],firn[N],secn[N];
10 struct edge{int to,next,w;}e[N*6];
11 struct node
12 {
13     int d,id;
14     bool operator <(const node& x)const{return x.d<d;}
15 };
16 priority_queue<node>q;
17 int read()
18 {
19     int x=0,f=1;char c=getchar();
20     while(c<0||c>9){if(x==-)f=-1;c=getchar();}
21     while(c>=0&&c<=9){x=x*10+c-0;c=getchar();}
22     return x*f;
23 }
24 void ins(int x,int y,int w)
25 {
26     cnt++;e[cnt].to=y;e[cnt].w=w;
27     e[cnt].next=first[x];first[x]=cnt;
28 }
29 void dijkstra()
30 {
31     memset(fir,0x3f,sizeof(fir));
32     memset(sec,0x3f,sizeof(sec));
33     for(int i=1;i<=k;i++)
34     {
35         fir[a[i]]=0;firn[a[i]]=a[i];
36         q.push((node){0,a[i]});
37     }
38     while(!q.empty())
39     {
40         node x=q.top();q.pop();
41         if(x.d>fir[x.id])continue;
42         int now=x.id;
43         for(int i=first[now];i;i=e[i].next)
44         {
45             int to=e[i].to;
46             if(firn[now]==firn[to])
47             {
48                 if(fir[now]+e[i].w<fir[to])
49                     fir[to]=fir[now]+e[i].w,q.push((node){fir[to],to});
50             }
51             else if(fir[now]+e[i].w<fir[to])
52             {
53                 sec[to]=fir[to];secn[to]=firn[to];
54                 fir[to]=fir[now]+e[i].w;firn[to]=firn[now];
55                 q.push((node){fir[to],to});
56 //                printf("[fir]%d %d %d [n] %d %d\n",now,to,fir[to],firn[now],firn[to]);
57             }
58             else if(fir[now]+e[i].w<sec[to])
59             {
60                 sec[to]=fir[now]+e[i].w;
61                 secn[to]=firn[now];
62 //                printf("[sec]%d %d %d [n] %d %d\n",now,to,sec[to],secn[now],secn[to]);
63             }
64         }
65     }
66 }
67 int main()
68 {
69     n=read();m=read();k=read();
70     for(int i=1;i<=k;i++)a[i]=read();
71     for(int i=1;i<=m;i++)
72     {
73         x=read();y=read();w=read();
74         ins(x,y,w);ins(y,x,w);
75     }
76     dijkstra();
77     for(int i=1;i<=n;i++)ans=min(ans,fir[i]+sec[i]);
78     printf("%d",ans);
79     return 0;
80 }
View Code

 

【SRM-08】解题报告

标签:first   信息   printf   alt   getchar   min   表示   bit   一个   

原文地址:http://www.cnblogs.com/zsnuo/p/7248042.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!