zoukankan      html  css  js  c++  java
  • [atARC089F]ColoringBalls

    对于一个字符串$s$,考虑构造一个等价的序列$a_{i}$,使得可以通过$a_{i}$来判定$s$是否合法

    由于当一个w被改变后不会再变回来,因此可以把w的地方断开,分为若干段,两个段是独立的,即变为了若干个仅含有r和b的段

    对于每一个段,令$a_{i}$为其中b的段数+1(序列$a_{i}$的长度即为总段数),其具有以下性质:

    1.不存在长度小于$a_{i}$的操作序列可以得到该段

    2.长为$a_{i}$的操作序列合法当且仅当以rb(若$a_{i}=1$则必须为r)开头

    对于性质1,每一次操作至多让b的段数增加1,同时第1次操作无法增加,因此至少需要$a_{i}$次操作

    对于性质2,首先$a_{i}le 2$时成立,然后归纳,对于新加入的一段b,如果新加入的操作是b直接覆盖即可,否则令上一次b操作的范围增大,用r将其断开即可

    然后如果不以rb开头,那么前两次操作不能使b的段数为1,类似结论1可得其无解

    根据这两个结论,$a_{i}$符合我们构造的条件,考虑枚举$a_{i}$,枚举方法如下:

    由于$a_{i}$为段数+1,因此该段长度$le max(2a_{i}-3,1)$,将所有段累加,又因为至少存在$m-1$个w的空隙($m$为段数),总长不超过$n$,即$sum_{i=1}^{m}max(2a_{i}-3,1)+m-1le n$

    令$a'_{i}=max(a_{i},2)-1$,有$max(2a_{i}-3,1)=2a'_{i}-1$,代入化简可得$sum_{i=1}^{m}a'_{i}le lfloorfrac{n+1}{2} floor$

    当$n=70$,$a'_{i}$的方案数为81156种,再枚举$a_{i}=1$的数字个数,总共有418662种(计算代码如下)

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define N 105
     4 int n,ans,f[N][N];
     5 int main(){
     6     n=35;
     7     f[0][0]=1;
     8     for(int i=1;i<=n;i++)
     9         for(int j=1;j<=i;j++)f[i][j]=f[i-j][min(i-j,j)]+f[i][j-1];
    10     for(int i=1;i<=n;i++)f[i][i]+=f[i-1][i-1];
    11     for(int i=0;i<=n;i++)ans+=f[i][i];
    12     printf("%d",ans);
    13 } 
    View Code

    对于一个$a_{i}$,我们要做两件事情:1.判定其是否合法;2.求出其对应的$s$数量

    判定合法:贪心,优先操作$a_{i}$较大的,不断找到下一个r和b,随便统计一下即可

    求方案数:先确定$a_{i}$的顺序,即将$a_{i}$打乱后不同的序列数,有$frac{m!}{prod_{i}(sum_{j=1}^{n}[a_{j}=i])!}$种

    将$s$的连续段缩为1个字母(记作$s'$),那么$s'$必然包含一个长为$l_{1}=2sum_{i=1}^{m}a'_{i}-1$的子序列(即尽量短的方案),同时自身也是一个长为$l_{2}=2sum_{i=1}^{m}a_{i}+1$的序列的子序列(即$l_{1}$补上两端的r和w)

    一个例子:对于$a_{i}={2,1,3}$,$l_{1}$为bwrwbrb,$l_{2}$为**wr**b**r**wrw**r**brb**rw**(其中加粗的为补上的r和w)

    然后$s$可以看作插板法划分为$l_{2}$段,其中有$l_{2}-l_{1}$段可以为空,即有$n+(l_{2}-l_{1})-1choose l_{2}-1$种

    总时间复杂度为$o(418662n)$,可以通过

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define N 205
     4 #define mod 1000000007
     5 pair<int,int>pos[N];
     6 int n,k,ans,a[N],sum[N],fac[N],inv[N];
     7 char s[N];
     8 void init(){
     9     fac[0]=inv[0]=inv[1]=1;
    10     for(int i=1;i<N-4;i++)fac[i]=1LL*fac[i-1]*i%mod;
    11     for(int i=2;i<N-4;i++)inv[i]=1LL*(mod-mod/i)*inv[mod%i]%mod;
    12     for(int i=1;i<N-4;i++)inv[i]=1LL*inv[i-1]*inv[i]%mod;
    13 }
    14 int c(int n,int m){
    15     return 1LL*fac[n]*inv[m]%mod*inv[n-m]%mod;
    16 }
    17 int calc(int m){
    18     if (pos[m].first==k)return 0;
    19     int s=0;
    20     for(int i=0;i<k;i++)sum[i]=1;
    21     for(int i=m;i;i--){
    22         if ((a[m-i+1])&&(pos[i].second==k))return 0;
    23         sum[pos[i].first]--;
    24         sum[pos[i].second]-=a[m-i+1];
    25     }
    26     for(int i=k-1;i>=0;i--){
    27         sum[i]+=sum[i+1];
    28         if (sum[i]<0)return 0;
    29     }
    30     s=fac[m];
    31     for(int i=1,j=1;i<=m;i=j){
    32         while ((j<=m)&&(a[i]==a[j]))j++;
    33         s=1LL*s*inv[j-i]%mod;
    34     }
    35     int l1=0,l2=0;
    36     for(int i=1;i<=m;i++)l1+=max(a[i],1);
    37     l1=l1*2-1;
    38     for(int i=1;i<=m;i++)l2+=a[i]+1;
    39     l2=l2*2+1;
    40     return 1LL*c(n+(l2-l1)-1,l2-1)*s%mod;
    41 }
    42 void dfs(int k,int las,int s){
    43     ans=(ans+calc(k-1))%mod;
    44     for(int i=1;i<k;i++)
    45         if (a[i]==1){
    46             a[i]=0;
    47             ans=(ans+calc(k-1))%mod;
    48         }
    49     for(int i=1;i<k;i++)
    50         if (!a[i])a[i]=1;
    51     for(a[k]=las;a[k]<=s;a[k]++)dfs(k+1,a[k],s-a[k]);
    52 }
    53 int main(){
    54     init();
    55     scanf("%d%d%s",&n,&k,s);
    56     for(int i=1,x=0,y=0;i<=n;i++){
    57         while ((x<k)&&(s[x]=='b'))x++;
    58         y=max(x,y);
    59         while ((y<k)&&(s[y]=='r'))y++;
    60         pos[i]=make_pair(x,y);
    61         if (x<k)x++;
    62         if (y<k)y++; 
    63     }
    64     dfs(1,1,(n+1)/2);
    65     printf("%d",ans);
    66 }
    View Code
  • 相关阅读:
    对PostgreSQL的 seq scan , bitmap index scan 和 index scan 的进一步理解
    C# IEnumerable和IEnumerator的区别,如何实现
    老板运煤问题及解决方案
    快速排序和简单排序
    给定数组,查找最小的k个元素或最大的k个元素
    一列数字的规则如下;1,1,2,3,5,8,13,21,34........ 求第30位数字是多少,用递规和非递归两种方法算法实现
    C# 如何利用反射来加载程序集,并调用程序集中有关类的方法
    http 请求 header 应用分析
    templatemonster 10231 面朝大海 你听到什么?
    足球俱乐部 网站模板 附带源文件 字体
  • 原文地址:https://www.cnblogs.com/PYWBKTDA/p/14133538.html
Copyright © 2011-2022 走看看