[关闭]
@suixinhita 2017-10-15T08:28:55.000000Z 字数 3396 阅读 868

郑外—衡中欢乐赛 之二

感想

大概是,药丸吧...
反正就是...兜兜转转,最后也爆出了10分...rating掉了三百...

题解

T1

此处输入图片的描述

不知道说自己智障还是神经(。)
关于括号的问题,不就是我之前那个 区间dp吗???
然后我们按照那个区间dp的思路,直接dp。
没了,注意点就是空格不能直接跳过,要化成

  1. #include<cstdio>
  2. #include<cstring>
  3. #include<algorithm>
  4. using namespace std;
  5. char s[60];
  6. bool f[60][60];
  7. int main()
  8. {
  9. int t,n;
  10. scanf("%d",&t);getchar();
  11. while(t--)
  12. {
  13. gets(s+1);
  14. n=strlen(s+1);
  15. memset(f,0,sizeof(f));
  16. for(int i=1;i<=n;++i)
  17. {
  18. int k;
  19. if(s[i]<'0'||s[i]>'9') continue;
  20. f[i][i]=1;
  21. k=i+1;while(s[k]==' '&&k<=n) f[i][k++]=1;
  22. k=i-1;while(s[k]==' '&&k>=1) f[k--][i]=1;
  23. k=i+1;while(k<=n&&s[k]>='0'&&s[k]<='9') f[i][k++]=1;
  24. k=i-1;while(k>=1&&s[k]>='0'&&s[k]<='9') f[k--][i]=1;
  25. }
  26. for(int l=2;l<=n;++l)
  27. {
  28. for(int i=1;i+l-1<=n;++i)
  29. {
  30. int j=i+l-1;
  31. for(int k=i+1;k<j;++k)
  32. if(s[k]=='+'||s[k]=='-'||s[k]=='/'||s[k]=='*')
  33. if(f[i][k-1]&&f[k+1][j]) f[i][j]=1;
  34. if(f[i+1][j-1]&&s[i]=='('&&s[j]==')') f[i][j]=1;
  35. int k,L,R;
  36. if(f[i][j]==1)
  37. {
  38. k=j+1;while(k<=n&&s[k]==' ') f[i][k++]=1;
  39. R=k-1;
  40. k=i-1;while(k>=1&&s[k]==' ') f[k--][i]=1;
  41. L=k+1;
  42. for(int i_=L;i_<=i;++i_)
  43. for(int j_=j;j_<=R;++j_)
  44. f[i_][j_]=1;
  45. }
  46. }
  47. }
  48. if(f[1][n]) puts("Yes");
  49. else puts("No");
  50. }
  51. return 0;
  52. }

T2

此处输入图片的描述

这个...拓扑排序。
我不是很会,但是基本上知道的,和bfs基本一样,需要注意多起点终点情况,以及入度要减去。
字符串哈希,也不苟什么哈希表了,直接MAP,建图直接跑拓扑。
好了。
注意:可能有多个入口和出口。

  1. #include<map>
  2. #include<queue>
  3. #include<cstdio>
  4. #include<cstring>
  5. #include<algorithm>
  6. #define ll long long
  7. using namespace std;
  8. const int N=50005;
  9. const int Q=1e9+7;
  10. const int seed=131;
  11. struct data{
  12. int to,next;
  13. }e[N<<1];
  14. int head[N],gs,in[N],out[N],m,n,tot;
  15. int cnt[N];
  16. char u[101],v[101];
  17. void add(int fr,int to)
  18. {
  19. in[to]++,out[fr]++,e[++gs].to=to,e[gs].next=head[fr],head[fr]=gs;
  20. }
  21. void bfs()
  22. {
  23. queue<int> q;
  24. for(int i=1;i<=tot;++i)
  25. if(in[i]==0) q.push(i),cnt[i]=1;
  26. while(!q.empty())
  27. {
  28. int u=q.front();q.pop();
  29. for(int i=head[u];i;i=e[i].next)
  30. {
  31. int v=e[i].to;
  32. cnt[v]=((ll)cnt[v]+cnt[u])%Q;
  33. in[v]--;
  34. if(in[v]==0) q.push(v);
  35. }
  36. }
  37. }
  38. ll hash(char s[])
  39. {
  40. ll h=0;
  41. int l=strlen(s+1);
  42. for(int i=1;i<=l;++i)
  43. h=(h*seed%Q+s[i]-'a')%Q;
  44. return h;
  45. }
  46. map <ll,int> M;
  47. void solve()
  48. {
  49. int x,y,s,t;
  50. int ans=0;
  51. for(int i=1;i<=m;++i)
  52. {
  53. scanf("%s%s",u+1,v+1);
  54. ll tmp=hash(u);
  55. ll tmp2=hash(v);
  56. if(M[tmp]) x=M[tmp];
  57. else x=++tot,M[tmp]=tot;
  58. if(M[tmp2]) y=M[tmp2];
  59. else y=++tot,M[tmp2]=tot;
  60. add(x,y);
  61. // printf("%d %d\n",x,y);
  62. }
  63. bfs();
  64. for(int i=1;i<=tot;++i)
  65. if(out[i]==0) ans=(cnt[i]+ans)%Q;
  66. printf("%d\n",ans);
  67. }
  68. int main()
  69. {
  70. // freopen("c.txt","r",stdin);
  71. // freopen("ch.txt","w",stdout);
  72. scanf("%d",&m);
  73. solve();
  74. return 0;
  75. }

T3

此处输入图片的描述

这道题,首先必须要能看出来是一个组合数(。)
比如我就没看出来...
然后我们推出组合数公式一看,好嘛。
还有限制。
这个限制,dp时候能绕开,但是组合数算是不好算的,所以我们想,用dp把他绕开。
那么我们就很清晰的知道,我们这时候,可以手动绕开这些不好的点。
所以说我我们设置dp的时候,需要这样:

即为第 个坏点处的方案数(不经过其他坏点)

这样的话我们排个序,可以很快的算出来答案了。

  1. #include<cstdio>
  2. #include<algorithm>
  3. #define ll long long
  4. using namespace std;
  5. const int N=2000005;
  6. const int Q=1e9+7;
  7. ll fac[N],inv[N];
  8. ll dp[N];
  9. struct data{
  10. ll x,y;
  11. bool friend operator <(data a,data b)
  12. {
  13. if(a.x!=b.x) return a.x<b.x;
  14. return a.y<b.y;
  15. }
  16. }p[3005];
  17. int m,n,k;
  18. ll quick_pow(ll x,ll k)
  19. {
  20. ll an=1;
  21. for(int i=k;i;i>>=1,x=x*x%Q)
  22. if(i&1) an=an*x%Q;
  23. return an;
  24. }
  25. void init()
  26. {
  27. fac[0]=1;inv[0]=1;
  28. for(int i=1;i<N;++i)
  29. fac[i]=(ll)fac[i-1]*i%Q;
  30. inv[N-1]=quick_pow(fac[N-1],Q-2);
  31. for(int i=N-2;i;--i)
  32. inv[i]=inv[i+1]*(i+1)%Q;
  33. }
  34. int c(int x,int y)
  35. {
  36. return fac[x]*inv[y]%Q*inv[x-y]%Q;
  37. }
  38. void solve()
  39. {
  40. init();
  41. sort(p+1,p+1+k);
  42. for(int i=1;i<=k;++i)
  43. {
  44. dp[i]=c(p[i].x+p[i].y,p[i].x);
  45. for(int j=1;j<i;++j)
  46. {
  47. if(p[i].x>=p[j].x&&p[i].y>=p[j].y)
  48. {
  49. dp[i]=(dp[i]-dp[j]*c(p[i].x-p[j].x+p[i].y-p[j].y,p[i].x-p[j].x)%Q+Q)%Q;
  50. }
  51. }
  52. }
  53. printf("%lld\n",dp[k]);
  54. }
  55. inline int read()
  56. {
  57. int x=0;char c=getchar();
  58. while(c<'0'||c>'9') c=getchar();
  59. while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
  60. return x;
  61. }
  62. int main()
  63. {
  64. n=read(),m=read();
  65. k=read();
  66. for(int i=1;i<=k;++i) p[i].x=read(),p[i].y=read();
  67. k++,p[k].x=n,p[k].y=m;
  68. solve();
  69. return 0;
  70. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注