Codeforces #533 div2 做题记录

A.

题解:枚举答案,验证

代码:

 1 #include<bits/stdc++.h>
 2 #define maxn 1005
 3 using namespace std;
 4 int n;
 5 int a[maxn];
 6 int main()
 7 {
 8     scanf("%d",&n);
 9     for(int i=1;i<=n;++i)scanf("%d",&a[i]);
10     int ans=1,val=100000000;
11     for(int k=1;k<=100;++k)
12     {
13         int t=0;
14         for(int i=1;i<=n;++i)
15         {
16             if(a[i]>k)t+=a[i]-(k+1);
17             if(a[i]<k)t+=(k-1)-a[i];
18         }
19         if(t<val)val=t,ans=k;
20     }
21     printf("%d %d\n",ans,val);
22     return 0;
23 }

 

B.

题解:考虑到每个长度为k的串的字母相同,用two-pointers维护出现次数,然后在长度为k字母相同的串结尾位置标记val=1,最后对每种字母DP就行

 1 #include<bits/stdc++.h>
 2 #define maxn 200005
 3 using namespace std;
 4 int n,k;
 5 char s[maxn];
 6 int val[maxn];
 7 int c[30],num;
 8 int dp[maxn];
 9 int main()
10 {
11     scanf("%d%d",&n,&k);
12     scanf("%s",s+1);
13     for(int l=1;l<=k;++l)
14     {
15         int t=s[l]-'a';
16         if(!c[t])num++;
17         c[t]++;
18     }
19     for(int r=k;r<=n;++r)
20     {
21         if(num==1)val[r]=1;
22         int l=r-k+1;
23         if(c[s[l]-'a']==1)num--;
24         c[s[l]-'a']--;
25         if(r!=n)
26         {
27             if(!c[s[r+1]-'a'])num++;
28             c[s[r+1]-'a']++;
29         }
30     }
31     int ans=0;
32     for(int p=0;p<26;++p)
33     {
34         for(int i=k;i<=n;++i)
35         {
36             dp[i]=dp[i-1];
37             if(s[i]-'a'==p&&dp[i]<dp[i-k]+val[i])dp[i]=dp[i-k]+val[i];
38         }
39         ans=max(ans,dp[n]);
40     }
41     printf("%d\n",ans);
42     return 0;
43 }

 

C.

题解:简单计数DP,按 mod 3 分类。

 1 #include<bits/stdc++.h>
 2 #define maxn 200005
 3 #define ll long long
 4 using namespace std;
 5 const ll mod = 1000000007;
 6 int n;
 7 ll l,r;
 8 ll val[4];
 9 ll dp[maxn][4];
10 int main()
11 {
12     scanf("%d%I64d%I64d",&n,&l,&r);
13     ll t=(r-l+1)/3,d=(r-l+1)%3;
14     if(d==0)val[0]=val[1]=val[2]=t;
15     if(d==1)
16     {
17         val[0]=val[1]=val[2]=t;
18         int x=(int)(l%3);
19         val[x]++;
20     }
21     if(d==2)
22     {
23         val[0]=val[1]=val[2]=t;
24         int x=(int)(l%3);
25         int y=(int)((l+1)%3);
26         val[x]++;val[y]++;
27     }
28     dp[0][0]=1;
29     for(int i=1;i<=n;++i)
30     {
31         dp[i][0]=(dp[i-1][0]*val[0]%mod+dp[i-1][1]*val[2]%mod+dp[i-1][2]*val[1]%mod)%mod;
32         dp[i][1]=(dp[i-1][0]*val[1]%mod+dp[i-1][1]*val[0]%mod+dp[i-1][2]*val[2]%mod)%mod;
33         dp[i][2]=(dp[i-1][0]*val[2]%mod+dp[i-1][1]*val[1]%mod+dp[i-1][2]*val[0]%mod)%mod;
34     }
35     int ans=dp[n][0];
36     printf("%d\n",ans);
37     return 0;
38 }

 

D.

题解:开p个队列,每次从可扩展点开始bfs就行

  1 #include<bits/stdc++.h>
  2 #define maxn 1005
  3 using namespace std;
  4 int n,m,p;
  5 char a[maxn][maxn];
  6 int s[maxn];
  7 struct node
  8 {
  9     int x,y;
 10     node(){}
 11     node(int X,int Y){x=X;y=Y;}
 12 };
 13 queue<node> q[10];
 14 stack<node> stk;
 15 int dis[maxn][maxn];
 16 int Ans[10];
 17 int main()
 18 {
 19     scanf("%d%d%d",&n,&m,&p);
 20     for(int i=1;i<=p;++i)scanf("%d",&s[i]);
 21     for(int i=1;i<=n;++i)scanf("%s",a[i]+1);
 22     for(int i=1;i<=n;++i)
 23         for(int j=1;j<=m;++j)
 24         {
 25             int k=a[i][j]-'0';
 26             if(1<=k&&k<=p)q[k].push(node(i,j)); 
 27         }
 28     while(1)
 29     {
 30         for(int k=1;k<=p;++k)
 31         {
 32             while(!q[k].empty())
 33             {
 34                 node u=q[k].front();
 35                 q[k].pop();
 36                 int x=u.x,y=u.y;
 37                 if(a[x-1][y]=='.'||a[x+1][y]=='.'||a[x][y-1]=='.'||a[x][y+1]=='.')
 38                 {
 39                     stk.push(u);
 40                     dis[x][y]=0;
 41                 }
 42             }
 43             while(!stk.empty())
 44             {
 45                 q[k].push(stk.top());
 46                 stk.pop(); 
 47             }
 48         }
 49         int flag=0;
 50         for(int k=1;k<=p;++k)if(!q[k].empty())flag=1;
 51         if(!flag)break;
 52         for(int k=1;k<=p;++k)
 53         {
 54             while(!q[k].empty())
 55             {
 56                 node u=q[k].front();q[k].pop();
 57                 int x=u.x,y=u.y;
 58                 if(dis[x][y]==s[k])
 59                 {
 60                     stk.push(u);
 61                     continue;
 62                 }
 63                 if(a[x-1][y]=='.')
 64                 {
 65                     dis[x-1][y]=dis[x][y]+1;
 66                     a[x-1][y]='0'+k;
 67                     q[k].push(node(x-1,y));
 68                 }
 69                 if(a[x+1][y]=='.')
 70                 {
 71                     dis[x+1][y]=dis[x][y]+1;
 72                     a[x+1][y]='0'+k;
 73                     q[k].push(node(x+1,y));
 74                 }
 75                 if(a[x][y-1]=='.')
 76                 {
 77                     dis[x][y-1]=dis[x][y]+1;
 78                     a[x][y-1]='0'+k;
 79                     q[k].push(node(x,y-1));
 80                 }
 81                 if(a[x][y+1]=='.')
 82                 {
 83                     dis[x][y+1]=dis[x][y]+1;
 84                     a[x][y+1]='0'+k;
 85                     q[k].push(node(x,y+1));
 86                 }
 87             }
 88             while(!stk.empty())
 89             {
 90                 node u=stk.top();
 91                 stk.pop();
 92                 q[k].push(u);
 93             }
 94         }
 95     }
 96     for(int i=1;i<=n;++i)
 97         for(int j=1;j<=m;++j)
 98         {
 99             int k=a[i][j]-'0';
100             if(1<=k&&k<=p)Ans[k]++;
101         }
102     for(int i=1;i<=p;++i)printf("%d ",Ans[i]);
103     return 0; 
104 }

 

E.

题解:

考虑这个序列,连续的一堆1是没有意义的,我们可以缩成一个;

然后就是1 2 2 2 …… 1 2 2 ……这样的形式;

对于每个1后面缀着的2,我们只能选1个,因此,只要有两个人在某段中共用一个1,那么这两个人就不能同时选;

这是个最大独立集问题,我们考虑转化成补图的最大团;

m=40,求最大团有不少方法,这里使用一个写起来简单的方法:随机化

考虑随机一个排列,然后贪心地选择点加入最大团,做个上千次就很对了。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int n,m;
 4 map<string,int> mp;
 5 bool has[42][100005];
 6 int a[42][42];
 7 int p[42];
 8 bool is[42];
 9 int ans,Ans[42];
10 int main()
11 {
12     scanf("%d%d",&n,&m);
13     int last=0,cnt=0;
14     for(int i=1;i<=n;++i)
15     {
16         int opt;
17         scanf("%d",&opt);
18         if(opt==1)++last;
19         else
20         {
21             string s;
22             cin>>s;
23             if(!mp.count(s))mp[s]=++cnt;
24             has[mp[s]][last]=1;
25         }
26     }
27     for(int i=1;i<=m;++i)
28     {
29         for(int j=i+1;j<=m;++j)
30         {
31             bool yes=1;
32             for(int k=1;k<=last;++k)if(has[i][k]&&has[j][k])yes=0;
33             if(yes)a[i][j]=a[j][i]=1;
34         }
35     }
36     for(int i=1;i<=m;++i)p[i]=i;
37     srand(time(NULL));
38     for(int t=1;t<=3000;++t)
39     {
40         random_shuffle(p+1,p+m+1);
41         memset(is,0,sizeof(is));
42         int num=0;
43         for(int i=1;i<=m;++i)
44         {
45             bool ok=1;
46             for(int j=1;j<i;++j)if(is[p[j]]&&!a[p[i]][p[j]])ok=0;
47             if(ok)is[p[i]]=1,num++;
48         }
49         if(num>ans)
50         {
51             ans=0;
52             for(int i=1;i<=m;++i)if(is[p[i]])Ans[++ans]=p[i];
53         }
54     }
55     printf("%d\n",ans);
56     return 0;
57 }

 

posted @ 2019-01-21 08:35  幽蝶  阅读(150)  评论(0编辑  收藏  举报