以后还是这样 25道题一起发 看着爽

noip失利之后发粪涂墙 刷了一波bzoj

题解:

bzoj1000 A+B问题

这题不同的人有不同的写法,我写了个线段树套Treap,应该还是挺简单的

但是看别的大神的代码跑的飞快就粘过来吧   这题竟然不用树套树,太强了

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<cstdlib>
  4. #include<cmath>
  5. #include<cstring>
  6. #include<algorithm>
  7. using namespace std;
  8. int main()
  9. {
  10. int a,b;
  11. cin>>a>>b;
  12. cout<<a+b;
  13. return ;
  14. }

bzoj1001 狼抓兔子

平面图最小割

建图方式比较奇怪,注意一下就可以了

  1. #include<iostream>
  2. #include<cstring>
  3. #include<cstdio>
  4. using namespace std;
  5. int n,m;
  6. int ne;
  7. struct data{int to,next,v;}e[];
  8. int head[];
  9. int h[],q[],ans;
  10. void insert(int u,int v,int w)
  11. {
  12. ne++;
  13. e[ne].to=v;
  14. e[ne].v=w;
  15. e[ne].next=head[u];
  16. head[u]=ne;
  17. }
  18. bool bfs()
  19. {
  20. int now,i;
  21. memset(h,-,sizeof(h));
  22. int t=,w=;
  23. q[t]=;h[]=;
  24. while(t<w)
  25. {
  26. now=q[t];t++;
  27. i=head[now];
  28. while(i)
  29. {
  30. if(e[i].v&&h[e[i].to]<)
  31. {
  32. q[w++]=e[i].to;
  33. h[e[i].to]=h[now]+;
  34. }
  35. i=e[i].next;
  36. }
  37. }
  38. if(h[n*m]==-)return ;
  39. return ;
  40. }
  41. int dfs(int x,int f)
  42. {
  43. if(x==n*m)return f;
  44. int i=head[x];
  45. int w,used=;
  46. while(i)
  47. {
  48. if(e[i].v&&h[e[i].to]==h[x]+)
  49. {
  50. w=f-used;
  51. w=dfs(e[i].to,min(w,e[i].v));
  52. e[i].v-=w;
  53. e[i+].v+=w;
  54. used+=w;
  55. if(used==f)return f;
  56. }
  57. i=e[i].next;
  58. }
  59. if(!used)h[x]=-;
  60. return used;
  61. }
  62. void dinic()
  63. {
  64. while(bfs())ans+=dfs(,0x7fffffff);
  65. }
  66. int main()
  67. {
  68. scanf("%d%d",&n,&m);
  69. int x;
  70. for(int i=;i<=n;i++)
  71. for(int j=;j<m;j++)
  72. {
  73. scanf("%d",&x);
  74. insert(m*(i-)+j,m*(i-)+j+,x);
  75. insert(m*(i-)+j+,m*(i-)+j,x);
  76. }
  77. for(int i=;i<n;i++)
  78. for(int j=;j<=m;j++)
  79. {
  80. scanf("%d",&x);
  81. insert(m*(i-)+j,m*(i)+j,x);
  82. insert(m*(i)+j,m*(i-)+j,x);
  83. }
  84. for(int i=;i<n;i++)
  85. for(int j=;j<m;j++)
  86. {
  87. scanf("%d",&x);
  88. insert(m*(i-)+j,m*(i)+j+,x);
  89. insert(m*(i)+j+,m*(i-)+j,x);
  90. }
  91. dinic();
  92. printf("%d",ans);
  93. return ;
  94. }

网络流

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<algorithm>
  4. #include<cmath>
  5. #include<cstring>
  6. #include<cstdlib>
  7. #include<set>
  8. #include<map>
  9. #include<vector>
  10. #include<stack>
  11. #include<queue>
  12. #define ll long long
  13. #define inf 2147383611
  14. #define MAXN 1001001
  15. #define MOD
  16. using namespace std;
  17. inline int read()
  18. {
  19. int x=,f=;
  20. char ch;ch=getchar();
  21. while(!isdigit(ch)) {if(ch=='-') f=-;ch=getchar();}
  22. while(isdigit(ch)) {x=x*+ch-'';ch=getchar();}
  23. return x*f;
  24. }
  25. int n,m,x,ans,lim;
  26. int to[MAXN*+],val[MAXN*+],first[MAXN*],next[MAXN*+],cnt;
  27. int dis[MAXN*];
  28. bool vis[MAXN*];
  29. void add(int u,int v,int d) {next[++cnt]=first[u],first[u]=cnt,val[cnt]=d,to[cnt]=v;}
  30. void spfa()
  31. {
  32. memset(dis,,sizeof(dis));
  33. queue <int> q;
  34. q.push();dis[]=,vis[]=;
  35. while(!q.empty())
  36. {
  37. int k=q.front();
  38. q.pop();
  39. vis[k]=;
  40. for(int i=first[k];i;i=next[i])
  41. if(dis[to[i]]>dis[k]+val[i])
  42. {
  43. dis[to[i]]=dis[k]+val[i];
  44. if(!vis[to[i]]) {q.push(to[i]);vis[to[i]]=;}
  45. }
  46. }
  47. printf("%d",dis[lim+]);
  48. }
  49. int main()
  50. {
  51. n=read(),m=read();
  52. ans=inf,lim=*(m-)*(n-);
  53. if(n==)
  54. {
  55. for(int i=;i<m;i++) {x=read(),ans=min(ans,x);}
  56. printf("%d",ans);return ;
  57. }
  58. if(m==)
  59. {
  60. for(int i=;i<n;i++) {x=read(),ans=min(ans,x);}
  61. printf("%d",ans);return ;
  62. }
  63. for(int i=;i<=n;i++)
  64. {
  65. for(int j=;j<m;j++)
  66. {
  67. x=read();
  68. if(i==) {add(lim+,j*,x);add(j*,lim+,x);continue;}
  69. if(i==n) {add(,(n-)*(m-)*+j*-,x);add((n-)*(m-)*+j*-,,x);continue;}
  70. add((i-)*(m-)*+j*,(i-)*(m-)*+j*-,x);add((i-)*(m-)*+j*-,(i-)*(m-)*+j*,x);
  71. }
  72. }
  73. for(int i=;i<n;i++)
  74. {
  75. for(int j=;j<=m;j++)
  76. {
  77. x=read();
  78. if(j==) {add(,(m-)*(i-)*+,x);add(*(m-)*(i-)+,,x);continue;}
  79. if(j==m) {add(lim+,i*(m-)*,x);add(i*(m-)*,lim+,x);continue;}
  80. add((i-)*(m-)*+*(j-),(i-)*(m-)*+*j-,x);add((i-)*(m-)*+*j-,(i-)*(m-)*+*(j-),x);
  81. }
  82. }
  83. for(int i=;i<n;i++)
  84. {
  85. for(int j=;j<m;j++)
  86. {
  87. x=read();
  88. add((i-)*(m-)*+*j,(i-)*(m-)*+*j-,x);add((i-)*(m-)*+*j-,(i-)*(m-)*+*j,x);
  89. }
  90. }
  91. spfa();
  92. }

对偶图

bzoj1002 轮状病毒

这题当年应该没多少人严格论证并写出来正解,时至今日已成为一道高精度练习题

网上严格论证。。。稀如凤毛麟角

找规律+高精度

  1. #include<iostream>
  2. #include<cstdio>
  3. using namespace std;
  4. struct data{
  5. int a[],len;
  6. };
  7. int n;
  8. data mul(data a,int k)
  9. {
  10. for(int i=;i<=a.len;i++)
  11. a.a[i]*=k;
  12. for(int i=;i<=a.len;i++)
  13. {
  14. a.a[i+]+=a.a[i]/;
  15. a.a[i]%=;
  16. }
  17. if(a.a[a.len+]!=)a.len++;
  18. return a;
  19. }
  20. data sub(data a,data b)
  21. {
  22. a.a[]+=;
  23. int j=;
  24. while(a.a[j]>=){a.a[j]%=;a.a[j+]++;j++;}
  25. for(int i=;i<=a.len;i++)
  26. {
  27. a.a[i]-=b.a[i];
  28. if(a.a[i]<){a.a[i]+=;a.a[i+]--;}
  29. }
  30. while(a.a[a.len]==)a.len--;
  31. return a;
  32. }
  33. int main()
  34. {
  35. data f[];f[].a[]=;f[].a[]=;
  36. f[].len=f[].len=;
  37. scanf("%d",&n);
  38. for(int i=;i<=n;i++)
  39. f[i]=sub(mul(f[i-],),f[i-]);
  40. for(int i=f[n].len;i>;i--)
  41. printf("%d",f[n].a[i]);
  42. return ;
  43. }

bzoj1003 物流运输

spfa+dp,dp[i][j]表示从第i天到第j天表示从第i天到第j天都能走的1~n最短路长度

f[i]表示前i天最小费用,初始化f[i]=dp[1][i]

递推式为f[i]=min{f[j]+dp[j+1][i]+k}(i>=2,j∈[1,i-1])

bzoj1004 Cards

置换群  Burnside定理  背包

反正就是个狂拽酷炫吊炸天的背包

具体可以看https://www.cnblogs.com/JoeFan/p/4299628.html这篇文章讲的挺好的

心疼当年考的小伙伴

  1. #include <cstdio>
  2. #include <cstring>
  3. #include <iostream>
  4. #include <algorithm>
  5. #define N 110
  6. using namespace std;
  7. typedef long long ll;
  8. int sr,sb,sg,n,m,mod;
  9. int cir[N][N],v[N],size[N];
  10. ll f[N][N][N],ans;
  11. int calc(int x)
  12. {
  13. int cnt=;
  14. memset(v,,sizeof(v));
  15. memset(size,,sizeof(size));
  16. for(int i=;i<=n;i++)
  17. {
  18. if(v[i])continue;
  19. int p=cir[x][i];
  20. cnt++;
  21. while(!v[p])v[p]=,size[cnt]++,p=cir[x][p];
  22. }
  23. memset(f,,sizeof(f));
  24. f[][][]=;
  25. for(int i=;i<=cnt;i++)
  26. for(int j=sr;j>=;j--)
  27. for(int k=sb;k>=;k--)
  28. for(int l=sg;l>=;l--)
  29. {
  30. if(j>=size[i])f[j][k][l]=(f[j][k][l]+f[j-size[i]][k][l])%mod;
  31. if(k>=size[i])f[j][k][l]=(f[j][k][l]+f[j][k-size[i]][l])%mod;
  32. if(l>=size[i])f[j][k][l]=(f[j][k][l]+f[j][k][l-size[i]])%mod;
  33. }
  34. return f[sr][sb][sg];
  35. }
  36. ll quick_my(ll x,int y)
  37. {
  38. ll ret=;
  39. while(y)
  40. {
  41. if(y&)ret=(ret*x)%mod;
  42. x=(x*x)%mod;
  43. y>>=;
  44. }
  45. return ret;
  46. }
  47. int main()
  48. {
  49. scanf("%d%d%d%d%d",&sr,&sb,&sg,&m,&mod);
  50. n=sr+sb+sg;
  51. for(int i=;i<=m;i++)
  52. for(int j=;j<=n;j++)
  53. scanf("%d",&cir[i][j]);
  54. m++;
  55. for(int i=;i<=n;i++)cir[m][i]=i;
  56. ll ans=;
  57. for(int i=;i<=m;i++)ans=(ans+calc(i))%mod;
  58. ans=(ans*quick_my(m,mod-))%mod;
  59. printf("%lld\n",ans);
  60. }

bzoj1005 明明的烦恼

又是一道结论题

  1. #include <cstdio>
  2. #include <cmath>
  3. #include <cstring>
  4. struct bignum {
  5. int l, a[];
  6.  
  7. bignum (int t) {
  8. l = ; memset(a, , sizeof());
  9. while (t != ) {
  10. a[++l] = t % ;
  11. t /= ;
  12. }
  13. if (l == ) l = ;
  14. }
  15.  
  16. void mul(int k) {
  17. for (int i = ; i <= l; i++)
  18. a[i] *= k;
  19. for (int i = ; i <= l; i++)
  20. if (a[i] >= ) {
  21. int t = i;
  22. do {
  23. a[t + ] += a[t] / ;
  24. a[t++] %= ;
  25. } while (a[t] >= );
  26. }
  27. while (a[l + ] > ) l++;
  28. }
  29.  
  30. void print() {
  31. printf("%d", a[l]);
  32. for (int i = l - ; i >= ; i--)
  33. printf("%04d", a[i]);
  34. printf("\n");
  35. }
  36. };
  37. int n, m = , tot = , d[], prime[], cnt[];
  38.  
  39. bool judge(int k) {
  40. for (int i = ; i <= sqrt(k); i++)
  41. if (k % i == ) return false;
  42. return true;
  43. }
  44.  
  45. void makelist(int n) {
  46. prime[] = ;
  47. for (int i = ; i <= n; i++)
  48. if (judge(i)) prime[++prime[]] = i;
  49. }
  50.  
  51. void compute(int k, int t) {
  52. for (int i = ; i <= prime[] && prime[i] <= k; i++) {
  53. int x = , n = k, p = prime[i];
  54. while (n != ) {
  55. x += n / p;
  56. n /= p;
  57. }
  58. cnt[i] += x * t;
  59. }
  60. }
  61.  
  62. int main() {
  63. //freopen("input.txt", "r", stdin);
  64. //freopen("output.txt", "w", stdout);
  65. scanf("%d", &n);
  66. for (int i = ; i <= n; i++) {
  67. scanf("%d", &d[i]);
  68. if (d[i] == -) m++;
  69. else tot += d[i] - ;
  70. }
  71.  
  72. makelist(n);
  73. memset(cnt, , sizeof(cnt));
  74. compute(n - , );
  75. compute(n - - tot, -);
  76. for (int i = ; i <= n; i++)
  77. if (d[i] != -) compute(d[i] - , -);
  78.  
  79. bignum ans = ;
  80. for (int i = ; i <= prime[]; i++)
  81. for (int j = ; j <= cnt[i]; j++)
  82. ans.mul(prime[i]);
  83. for (int i = ; i <= n - - tot; i++)
  84. ans.mul(m);
  85. ans.print();
  86. return ;
  87. }

代码

prufer序列的相关知识可以见https://www.cnblogs.com/CSU3901130321/p/4898261.html这篇博客

bzoj1006 神奇的国度

简单弦图的染色

可以见CDQ的论文

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<cstdlib>
  4. #include<algorithm>
  5. #include<cstring>
  6. #define inf 0x7fffffff
  7. #define ll long long
  8. using namespace std;
  9. inline ll read()
  10. {
  11. ll x=,f=;char ch=getchar();
  12. while(ch>''||ch<''){if(ch=='-')f=-;ch=getchar();}
  13. while(ch>=''&&ch<=''){x=x*+ch-'';ch=getchar();}
  14. return x*f;
  15. }
  16. int n,m,cnt,ans;
  17. int head[],d[],q[],col[],hash[];
  18. bool vis[];
  19. struct data{int to,next;}e[];
  20. void ins(int u,int v)
  21. {e[++cnt].to=v;e[cnt].next=head[u];head[u]=cnt;}
  22. int main()
  23. {
  24. n=read();m=read();
  25. for(int i=;i<=m;i++)
  26. {
  27. int u=read(),v=read();
  28. ins(u,v);ins(v,u);
  29. }
  30. for(int i=n;i;i--)
  31. {
  32. int t=;
  33. for(int j=;j<=n;j++)
  34. {
  35. if(!vis[j]&&d[j]>=d[t])t=j;
  36. }
  37. vis[t]=;q[i]=t;
  38. for(int j=head[t];j;j=e[j].next)
  39. d[e[j].to]++;
  40. }
  41. for(int i=n;i>;i--)
  42. {
  43. int t=q[i];
  44. for(int j=head[t];j;j=e[j].next)hash[col[e[j].to]]=i;
  45. int j;
  46. for(j=;;j++)if(hash[j]!=i)break;
  47. col[t]=j;
  48. if(j>ans)ans=j;
  49. }
  50. printf("%d",ans);
  51. return ;
  52. }

bzoj1007 水平可见直线

终于不是结论题了

水题 离散化 单调栈 完事

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<algorithm>
  4. #include<cstdlib>
  5. #include<cmath>
  6. #include<cstring>
  7. using namespace std;
  8. const double eps=1e-;
  9. struct Vec{double a,b;int rank;}lines[];
  10. Vec st[];int top;
  11. bool cmp1(Vec x,Vec y)
  12. {
  13. if(fabs(x.a-y.a)<eps)return x.b<y.b;
  14. return x.a<y.a;
  15. }
  16. int check[];
  17. double Sv(Vec a,Vec b){return (b.b-a.b)/(a.a-b.a);}
  18. void Push(Vec a)
  19. {
  20. while(top)
  21. {
  22. if(fabs(st[top].a-a.a)<eps)--top;
  23. else if(top> && Sv(a,st[top-])<=Sv(st[top],st[top-]))--top;
  24. else break;
  25. }
  26. st[++top]=a;
  27. }
  28. int main()
  29. {
  30. int n;
  31. scanf("%d",&n);
  32. for(int i=;i<=n;i++){scanf("%lf%lf",&lines[i].a,&lines[i].b);lines[i].rank=i;}
  33. sort(lines+,lines+n+,cmp1);
  34. for(int i=;i<=n;i++)Push(lines[i]);
  35. for(int i=;i<=top;i++)check[st[i].rank]=;
  36. for(int i=;i<=n;i++)if(check[i])cout<<i<<" ";
  37. return ;
  38. }

bzoj1008 越狱

数学题  要时刻注意%还是不%,%完了是正的负的

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<cstring>
  4. #include<cstdlib>
  5. #define mod 100003
  6. #define ll long long
  7. using namespace std;
  8. ll m,n;
  9. ll qpow(ll a,ll b)
  10. {
  11. ll c=,d=a%mod;
  12. while (b>)
  13. {
  14. if (b&)
  15. c=(c%mod*d%mod)%mod;
  16. b>>=;
  17. d=(d%mod*d%mod)%mod;
  18. }
  19. return c;
  20. }
  21. int main()
  22. {
  23. scanf("%lld%lld",&m,&n);
  24. long long ans=qpow(m,n);
  25. ans=ans-m*qpow(m-,n-)%mod;
  26. if (ans<) ans+=mod;
  27. printf("%lld",ans);
  28. return ;
  29. }

bzoj1009 GT考试

KMP+矩阵乘法加速DP

递推式很好想

设a[k][j]为k位后面加一个字母转移到j的方案数

dp[i][j]=∑dp[i−1][k]∗a[k][j](0<=k<=m−1)

因为是线性的 可以矩阵优化

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<algorithm>
  4. #include<cstdlib>
  5. #include<cmath>
  6. #include<cstring>
  7. #define ll long long
  8. int m,mod;
  9. using namespace std;
  10. struct mat
  11. {
  12. ll a[][];
  13. mat operator*(const mat &y)const
  14. {
  15. mat res;
  16. memset(res.a,,sizeof(res.a));
  17. for(int i=;i<m;i++)
  18. for(int j=;j<m;j++)
  19. for(int k=;k<m;k++)
  20. {
  21. res.a[i][j]+=a[i][k]*y.a[k][j];
  22. res.a[i][j]%=mod;
  23. }
  24. return res;
  25. }
  26. }a,b;
  27. mat ksm(mat A,int n)
  28. {
  29. mat res;
  30. if(n==) return A;
  31. res=ksm(A,n/);
  32. res=res*res;
  33. if(n%==)res=res*A;
  34. return res;
  35. }
  36. void mul(int a[][],int b[][],int ans[][])
  37. {
  38. int tmp[][];
  39. for(int i=;i<m;i++)
  40. for(int j=;j<m;j++)
  41. {
  42. tmp[i][j]=;
  43. for(int k=;k<m;k++)
  44. tmp[i][j]=(tmp[i][j]+a[i][k]*b[k][j])%mod;
  45. }
  46. for(int i=;i<m;i++)
  47. for(int j=;j<m;j++)
  48. ans[i][j]=tmp[i][j];
  49. }
  50. int sum;
  51. char ch[];
  52. int nxt[];
  53. int main()
  54. {
  55. int n;
  56. scanf("%d%d%d",&n,&m,&mod);
  57. scanf("%s",ch+);
  58. int j=;
  59. for(int i=;i<=m;i++)
  60. {
  61. for(;j> && ch[j+]!=ch[i];j=nxt[j]);
  62. if(ch[j+]==ch[i])j++;
  63. nxt[i]=j;
  64. }
  65. for(int i=;i<m;i++)
  66. for(int j=;j<=;j++)
  67. {
  68. int t=i;
  69. for(;t>&&ch[t+]-''!=j;t=nxt[t]);
  70. if(ch[t+]-''==j)t++;
  71. if(t!=m)b.a[t][i]=(b.a[t][i]+)%mod;
  72. }
  73. for(int i=;i<m;i++)a.a[i][i]=;
  74. while(n)
  75. {
  76. if(n&)a=a*b;
  77. b=b*b;
  78. n>>=;
  79. }
  80. for(int i=;i<m;i++)(sum+=a.a[i][])%=mod;
  81. printf("%d",sum);
  82. return ;
  83. }

bzoj1010 玩具装箱toy

斜率优化

dp[i]=min(dp[j]+(sum[i]-sum[j]+i-j-1-L)^2) (j<i)

推一推 搞成令f[i]=sum[i]+i,c=1+l

然后用一个单调队列维护下凸壳就好了

  1. #include<cstdio>
  2. #include<cstring>
  3. #include<cmath>
  4. #include<iostream>
  5. #include<algorithm>
  6. #include<cstdlib>
  7. #define ll long long
  8. using namespace std;
  9. int n,L,l,r;
  10. int c[],q[];
  11. ll s[],f[];
  12. double slop(int j,int k){return (f[k]-f[j]+(s[k]+L)*(s[k]+L)-(s[j]+L)*(s[j]+L))/(2.0*(s[k]-s[j]));}
  13. int main()
  14. {
  15. scanf("%d%d",&n,&L);L++;
  16. for(int i=;i<=n;i++)scanf("%d",&c[i]);
  17. for(int i=;i<=n;i++)s[i]=s[i-]+c[i];
  18. for(int i=;i<=n;i++)s[i]+=i;
  19. l=;r=;q[++r]=;
  20. for(int i=;i<=n;i++)
  21. {
  22. while(l<r && slop(q[l],q[l+])<=s[i])l++;
  23. int t=q[l];
  24. f[i]=f[t]+(s[i]-s[t]-L)*(s[i]-s[t]-L);
  25. while(l<r && slop(q[r],i)<slop(q[r-],q[r]))r--;
  26. q[++r]=i;
  27. }
  28. printf("%lld\n",f[n]);
  29. return ;
  30. }

bzoj1011 遥远的行星

puts("-nan");

果然HNaNOI

正经做也是可以的

由于“误差不超过5%”

当数据小于50时,暴力    大于50时,用到一些估算技巧

没有做过这么奇怪的题呢

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. double m[], sum[];
  4. int main()
  5. {
  6. int n;
  7. double a, ans;
  8. scanf("%d%lf", &n, &a);
  9. for(int j = ; j <= n; ++j)
  10. {
  11. int i = (int)(a * j + 1e-);
  12. scanf("%lf", m + j);
  13. ans = ;
  14. if(j <= )
  15. for(int k = ; k <= i; ++k)
  16. ans += m[k] * m[j] / (j - k);
  17. else
  18. ans = sum[i] * m[j] / (j - i / );
  19. printf("%f\n", ans);
  20. sum[j] = sum[j - ] + m[j];
  21. }
  22. return ;
  23. }

bzoj1012  最大数

单调队列,二分查找

但其实单调栈也是可以的。。。

看到网上一片线段树的时候我以为我做错了

  1. #include<cstdio>
  2. #include<cstdlib>
  3. #include<cmath>
  4. #include<cstring>
  5. #include<algorithm>
  6. using namespace std;
  7. int n,m,last,mod;
  8. int q[],id[],head,tail;
  9. void add(int x)
  10. {
  11. while (q[tail]<=x && tail) tail--;
  12. q[++tail]=x;id[tail]=++n;
  13. }
  14. int query(int x)
  15. {
  16. int l=n-x+;
  17. int k=lower_bound(id+head,id+tail+,l)-id;
  18. return q[k];
  19. }
  20. int main()
  21. {
  22. scanf("%d%d",&m,&mod);
  23. char ch[];
  24. int x;
  25. head=;tail=;
  26. while(m--)
  27. {
  28. scanf("%s%d",ch,&x);
  29. if(ch[]=='A') add((x+last)%mod);
  30. else printf("%d\n",last=query(x));
  31. }
  32. return ;
  33. }

bzoj1013 Sphere(名字太长辣)

高斯消元法裸题

但是推方程组用了我3张纸

  1. #include<cstdio>
  2. #include<algorithm>
  3. #include<cstring>
  4. #include<iostream>
  5. #include<cmath>
  6. using namespace std;
  7. #define zero 1e-6
  8. int n;
  9. double ans[],a[][],d[][];
  10. void init() {
  11. cin>>n;
  12. for (int i=; i<=n+; i++)
  13. for (int j=; j<=n; j++) cin>>d[i][j];
  14. for (int i=; i<=n; i++) {
  15. for (int j=; j<=n; j++)
  16. a[i][j] = * (d[i+][j]-d[i][j]),
  17. a[i][n+] += d[i+][j] * d[i+][j] - d[i][j] * d[i][j];
  18. }
  19. memset(ans,,sizeof ans);
  20. }
  21.  
  22. void gauss() {
  23. for (int i=; i<n; i++) {
  24. if (fabs(a[i][i])<zero)
  25. for (int j=i+; j<=n; j++)
  26. if (abs(a[j][i])>zero) {
  27. for (int k=; k<=n+; k++) swap(a[i][k],a[j][k]);
  28. break;
  29. }
  30. for (int j=i+; j<=n; j++) {
  31. double x = a[j][i] / a[i][i];
  32. for (int k=i; k<=n+; k++) a[j][k] -= a[i][k] * x;
  33. }
  34. }
  35. ans[n]=a[n][n+]/a[n][n];
  36. for (int i=n-; i; i--) {
  37. for (int j=i+; j<=n; j++) a[i][n+] -= ans[j]*a[i][j];
  38. ans[i] = a[i][n+] / a[i][i];
  39. }
  40. }
  41.  
  42. void print() {
  43. for (int i=; i<n; i++) printf("%.3lf ",ans[i]);
  44. printf("%.3lf\n",ans[n]);
  45. }
  46.  
  47. int main() {
  48. init();
  49. gauss();
  50. print();
  51. return ;
  52. }

bzoj1014 火星人

Splay,我写了题解

传送门:http://www.cnblogs.com/Kong-Ruo/p/7895957.html

bzoj1015 星球大战

并查集,操作离线

不得不说脑洞挺大的

将操作倒过来

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<cstring>
  4. #include<algorithm>
  5. using namespace std;
  6. int fa[];
  7. inline int read()
  8. {
  9. int x=;char ch=getchar();
  10. while(ch<''||ch>''){ch=getchar();}
  11. while(ch>=''&&ch<=''){x=x*+ch-'';ch=getchar();}
  12. return x;
  13. }
  14. int n,m;
  15. int u,v,atk[],d[],ans[],vis[];
  16. inline int find(int x){return x==fa[x]?x:fa[x]=find(fa[x]);}
  17. int first[],to[],next[],cnt=;
  18. void add(int u,int v){to[++cnt]=v;next[cnt]=first[u];first[u]=cnt;}
  19. int tmp;
  20. void destroy(int x)
  21. {
  22. int p=find(x),q;
  23. for(int i=first[x];i;i=next[i])
  24. {
  25. if(!vis[to[i]])continue;
  26. q=find(to[i]);
  27. if(p!=q){fa[q]=p;tmp--;}
  28. }
  29. }
  30. int main()
  31. {
  32. n=read();m=read();
  33. for(int i=;i<n;i++)fa[i]=i;
  34. for(int i=;i<=m;i++){u=read(),v=read();add(u,v);add(v,u);}
  35. int k=read();
  36. for(int i=;i<=k;i++){atk[i]=read();d[atk[i]]=;}
  37. for(int i=;i<n;i++)
  38. {
  39. if(!d[i])
  40. {
  41. tmp++;
  42. destroy(i);
  43. vis[i]=;
  44. }
  45. }
  46. ans[k+]=tmp;
  47. for(int i=k;i>;i--)
  48. {
  49. tmp++;
  50. destroy(atk[i]);
  51. vis[atk[i]]=;
  52. ans[i]=tmp;
  53. }
  54. for(int i=;i<=k+;i++)printf("%d\n",ans[i]);
  55. return ;
  56. }

bzoj1016 最小生成树计数

Kruskal+乘法原理

另:千万不要一看到并查集就写路径压缩!!!

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<cstring>
  4. #include<algorithm>
  5. using namespace std;
  6. const int mod=;
  7. int fa[];
  8. struct edge{int x,y,v;}e[];
  9. struct EDG{int l,r,v;}a[];
  10. inline int read()
  11. {
  12. int x=;char ch=getchar();
  13. while(ch<''||ch>''){ch=getchar();}
  14. while(ch>=''&&ch<=''){x=x*+ch-'';ch=getchar();}
  15. return x;
  16. }
  17. int n,m,cnt,cntt,ans,sum;
  18. bool cmp(edge a,edge b){return a.v<b.v;}
  19. inline int find(int x){return x==fa[x]?x:find(fa[x]);} //这里不能路径压缩!!!WA了好几遍
  20. void kruskal()
  21. {
  22. sort(e+,e+m+,cmp);
  23. for(int i=;i<=m;i++)
  24. {
  25. if(e[i].v!=e[i-].v){a[++cnt].l=i;a[cnt-].r=i-;}
  26. int p=find(e[i].x),q=find(e[i].y);
  27. if(p!=q){fa[p]=q;a[cnt].v++;cntt++;}
  28. }
  29. a[cnt].r=m;
  30. }
  31. void dfs(int x,int c,int k)
  32. {
  33. if(c==a[x].r+)
  34. {
  35. if(k==a[x].v)sum++;
  36. return;
  37. }
  38. int p=find(e[c].x),q=find(e[c].y);
  39. if(p!=q)
  40. {
  41. fa[p]=q;
  42. dfs(x,c+,k+);
  43. fa[p]=p;fa[q]=q;
  44. }
  45. dfs(x,c+,k);
  46. }
  47. void kkruskal()
  48. {
  49. for(int i=;i<=n;i++)fa[i]=i;
  50. for(int i=;i<=cnt;i++)
  51. {
  52. sum=;
  53. dfs(i,a[i].l,);
  54. ans=(ans*sum)%mod;
  55. for(int j=a[i].l;j<=a[i].r;j++)
  56. {
  57. int p=find(e[j].x),q=find(e[j].y);
  58. if(p!=q)fa[p]=q;
  59. }
  60. }
  61. }
  62. int main()
  63. {
  64. ans++;
  65. n=read();m=read();
  66. for(int i=;i<=n;i++)fa[i]=i;
  67. for(int i=;i<=m;i++)e[i].x=read(),e[i].y=read(),e[i].v=read();
  68. kruskal();
  69. if(cntt!=n-){printf("");return ;}
  70. kkruskal();
  71. printf("%d",ans);
  72. return ;
  73. }

bzoj1017 魔兽地图DotR

斗地主加强版

装备合成形成一个森林

预处理出高级物品的力量,价格,购买上限

用f[i][j][k]表示前i个物品 有j个用于合成 总花费为k时提供的力量最大值

对于以a为根的子树枚举合成b个物品,再把剩下的钱买不用于合成的物品

用ff[i][j]表示以a为根的子树里的前i个节点花费为j时可以获得的力量最大值

再d一遍

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<algorithm>
  4. #include<cstring>
  5. #include<cstdlib>
  6. #include<cmath>
  7. using namespace std;
  8. inline int read()
  9. {
  10. int x=,f=;
  11. char ch=getchar();
  12. while(!isdigit(ch)){if(ch=='-')f=-;ch=getchar();}
  13. while(isdigit(ch)){x=*x+f-'';ch=getchar();}
  14. return x*f;
  15. }
  16. const int maxn=;
  17. const int inf=;
  18. int dp[maxn][maxn*][],c[maxn][maxn*],f[maxn][maxn*];
  19. int n,m,t;
  20. int lim[maxn],pri[maxn],p[maxn];
  21. int rd[maxn];
  22. struct EDG
  23. {
  24. int to,next,val;
  25. }e[maxn*maxn*];
  26. int first[maxn],cnt;
  27. inline void add(int u,int v,int w)
  28. {
  29. e[++cnt].to=v;
  30. e[cnt].next=first[u];
  31. e[cnt].val=w;
  32. first[u]=cnt;
  33. rd[v]++;
  34. }
  35. char ch[];
  36. void dfs(int x)
  37. {
  38. if(!first[x])
  39. {
  40. lim[x]=min(lim[x],m/pri[x]);
  41. for(int i=;i<=lim[x];i++)
  42. for(int j=i;j<=lim[x];j++)
  43. dp[x][i][j*pri[x]]=(j-i)*p[x];
  44. return;
  45. }
  46. lim[x]=;
  47. for(int i=first[x];i;i=e[i].next)
  48. {
  49. dfs(e[i].to);
  50. lim[x]=min(lim[x],lim[e[i].to]/e[i].val);
  51. pri[x]+=e[i].val*pri[e[i].to];
  52. }
  53. lim[x]=min(lim[x],m/pri[x]);
  54. memset(c,-0x3f3f3f3f,sizeof(c));
  55. c[][]=;
  56. for(int i=lim[x];i>=;i--)
  57. {
  58. int cc=;
  59. for(int j=first[x];j;j=e[j].next)
  60. {
  61. cc++;
  62. for(int k=;k<=m;k++)
  63. for(int l=;l<=k;l++)
  64. c[cc][k]=max(c[cc][k],c[cc-][k-l]+dp[e[j].to][i*e[j].val][l]);
  65. }
  66. for(int j=;j<=i;j++)
  67. for(int k=;k<=m;k++)
  68. dp[x][j][k]=max(dp[x][j][k],c[cc][k]+p[x]*(i-j));
  69. }
  70.  
  71. }
  72. int main()
  73. {
  74. memset(dp,-0x3f3f3f3f,sizeof(dp));
  75. scanf("%d%d",&n,&m);
  76. int x,y,uu;
  77. for(int i=;i<=n;i++)
  78. {
  79. scanf("%d%d",&p[i]);
  80. scanf("%s",ch);
  81. if(ch[]=='B')scanf("%d%d",&pri[i],&lim[i]);
  82. else
  83. {
  84. scanf("%d",&x);
  85. for(int j=;j<=x;j++)
  86. {
  87. scanf("%d%d",&y,&uu);
  88. add(i,y,uu);
  89. }
  90. }
  91. }
  92. for(int z=;z<=n;z++)
  93. {
  94. if(!rd[z])
  95. {
  96. dfs(z);
  97. t++;
  98. for(int i=;i<=m;i++)
  99. for(int j=;j<=i;j++)
  100. for(int k=;k<=lim[z];k++)
  101. f[t][i]=max(f[t][i],f[t-][j]+dp[z][k][i-j]);
  102. }
  103. }
  104. int ans=-;
  105. for(int i=;i<=m;i++)ans=max(ans,f[t][i]);
  106. printf("%d\n",ans);
  107. }

bzoj1008 堵塞的交通Traffic

本来以为线段树都是慈眉善目的

线段树每个节点记一个2*2矩阵中6组连通性

走的时候左边的节点先走到最左边,右边节点先走到最右边

然后往中间走

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<algorithm>
  4. #include<cstring>
  5. #include<cstdlib>
  6. #define l(x) (x<<1)
  7. #define r(x) ((x<<1)|1)
  8. using namespace std;
  9. const int maxn=;
  10. char opt[];
  11. int x1,y1,x2,y2,c;
  12. struct Segtree
  13. {
  14. struct Martix
  15. {
  16. int a1[][];
  17. int a2[];
  18. };
  19.  
  20. struct Treenode
  21. {
  22. int l,r;
  23. Martix s;
  24. }tr[maxn];
  25. int bl[maxn][];
  26.  
  27. Martix upd(Martix s1,Martix s2,int b[])
  28. {
  29. Martix res;
  30. for(int i=;i<=;i++)
  31. for(int j=;j<=;j++)
  32. res.a1[i][j]=s1.a1[i][] && b[] && s2.a1[][j] || s1.a1[i][] && b[] && s2.a1[][j];
  33. res.a2[]=s1.a2[] || s1.a1[][] && b[] && s2.a2[] && b[] && s1.a1[][];
  34. res.a2[]=s2.a2[] || s2.a1[][] && b[] && s1.a2[] && b[] && s2.a1[][];
  35. return res;
  36. }
  37.  
  38. Martix getc(int id,int l,int r)
  39. {
  40. int mid=(tr[id].l+tr[id].r)>>;
  41. if(l<=tr[id].l && r>=tr[id].r) return tr[id].s;
  42. else if(l>mid)return getc(r(id),l,r);
  43. else if(r<=mid)return getc(l(id),l,r);
  44. else return upd(getc(l(id),l,r),getc(r(id),l,r),bl[id]);
  45. }
  46.  
  47. void update(bool f,int id,int sx,int sy,int gx,int gy)
  48. {
  49. int mid=(tr[id].l+tr[id].r)>>;
  50. if(sx==gx && sy==mid)
  51. {
  52. bl[id][sx]=f;
  53. tr[id].s=upd(tr[l(id)].s,tr[r(id)].s,bl[id]);
  54. }
  55. else if(tr[id].l==tr[id].r)
  56. tr[id].s.a1[][]=tr[id].s.a1[][]=tr[id].s.a2[]=tr[id].s.a2[]=f;
  57. else
  58. {
  59. if(gy<=mid)update(f,l(id),sx,sy,gx,gy);
  60. else update(f,r(id),sx,sy,gx,gy);
  61. tr[id].s=upd(tr[l(id)].s,tr[r(id)].s,bl[id]);
  62. }
  63. }
  64. void build(int id,int l,int r)
  65. {
  66. tr[id].l=l;tr[id].r=r;
  67. if(l==r)
  68. {
  69. tr[id].s.a1[][]=tr[id].s.a1[][]=;
  70. return;
  71. }
  72. int mid=(l+r)>>;
  73. build(l(id),l,mid);
  74. build(r(id),mid+,r);
  75. }
  76.  
  77. void query(int sx,int sy,int gx,int gy)
  78. {
  79. Martix L=getc(,,sy),Mid=getc(,sy,gy),R=getc(,gy,c);
  80. int res=;
  81. for(int i=;i<=;i++)
  82. for(int j=;j<=;j++)
  83. if(Mid.a1[i][j]&&(i==sx||L.a2[])&&(j==gx||R.a2[])){res=;break;}
  84. if(res)printf("Y\n");
  85. else printf("N\n");
  86. }
  87. }seg;
  88. int main()
  89. {
  90. scanf("%d",&c);
  91. seg.build(,,c);
  92. while() {
  93. scanf("%s",opt);
  94. if(opt[]=='E') break;
  95. scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
  96. --x1; --x2;
  97. if(y1>y2) {
  98. swap(x1,x2);
  99. swap(y1,y2);
  100. }
  101. if(opt[]=='O') seg.update(,,x1,y1,x2,y2);
  102. else if(opt[]=='C') seg.update(,,x1,y1,x2,y2);
  103. else seg.query(x1,y1,x2,y2);
  104. }
  105. return ;
  106. }

bzoj1019 汉诺塔

一个经典的汉诺塔型递推

结合汉诺塔&&BLAH,可想到递推方程: f[x][i] ,g[x][i] 分别表示,当前x柱上有i个圆盘,将它们移至任意另一个柱的操作数,和另一柱子的编号.(如上,这显然对任意连续的i个圆盘,都是唯一固定的)

f[x][i],g[x][i] 可由 f[][i-1],g[][i-1] 推得:

汉诺塔的经典转移,先做子问题把x柱上的i-1个圆盘移走,再把第i个大圆盘移走..

若设y=g[x][i-1],z=1+2+3-y-x(即除x,y以外的柱子编号)

即1) x上i-1个圆盘移至y上

2)由于不能对一个圆盘进行重复操作,所以必是将x上的第i个圆盘,移至z

由于i个圆盘还没叠到一起,所以接下来显然还要再次移动y上的i-1个,这时需要分类讨论:

若 f[y][i-1]=z:

3)移到z后,便结束了

综合以上,这种情况下,f[x][i]=f[x][i-1]+1+f[y][i-1],g[x][i]=z

若f[y][i-1]=x:

3)i-1个圆盘移至x

4)不能对一个圆盘进行重复操作,所以必将z上的第i个圆盘,移至y

5)因g[x][i-1]=y,所以x上i-1个圆盘移至y,结束

综合以上,这种情况下,f[x][i]=f[x][i-1]+1+f[y][i-1]+1+f[x][i-1],g[x][i]=y

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<cstdlib>
  4. #include<cstring>
  5. #include<algorithm>
  6. #include<cmath>
  7. #define LL long long
  8. using namespace std;
  9. int v[],n,g[][];
  10. LL f[][];
  11. int main()
  12. {
  13. scanf("%d",&n);
  14. for (int i=;i<=;i++)
  15. {
  16. char s[];
  17. scanf("%s",s);
  18. int from=s[]-'A'+,to=s[]-'A'+;
  19. if (v[from]) continue;
  20. v[from]=;
  21. g[from][]=to,f[from][]=;
  22. }
  23. for (int i=;i<=n;i++)
  24. for (int j=;j<=;j++)
  25. {
  26. int y=g[j][i-];
  27. int z=-y-j;
  28. f[j][i]=f[j][i-]+;
  29. if (z==g[y][i-])
  30. {
  31. f[j][i]+=f[y][i-];
  32. g[j][i]=z;
  33. }
  34. else
  35. {
  36. f[j][i]+=f[y][i-]++f[j][i-];
  37. g[j][i]=y;
  38. }
  39. }
  40. cout<<f[][n]<<endl;
  41. return ;
  42. }

bzoj1020 安全的航线

看着莫队的论文战战兢兢的做完这道题

计算几何入门题

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<cstdlib>
  4. #include<cmath>
  5. #include<cstring>
  6. #include<algorithm>
  7. using namespace std;
  8. const double eps=1e-;
  9. const int MAXQ=;
  10. int n,m;double ans;
  11. int dcmp(double a)
  12. {
  13. if(fabs(a)<eps)return ;
  14. else return a>?:-;
  15. }
  16. struct Vector
  17. {
  18. double x,y;
  19. Vector operator +(const Vector &a)const{return (Vector){x+a.x,y+a.y};}
  20. Vector operator -(const Vector &a)const{return (Vector){x-a.x,y-a.y};}
  21. bool operator ==(const Vector &a)const{return dcmp(x-a.x)== && dcmp(y-a.y)==;}
  22. Vector operator *(const double &a)const{return (Vector){x*a,y*a};}
  23. Vector operator /(const double &a)const{return (Vector){x/a,y/a};}
  24. void Read(){scanf("%lf %lf",&x,&y);}
  25. }temp[];
  26. double dot(Vector a,Vector b){return a.x*b.x+a.y*b.y;}
  27. double Length(Vector a){return sqrt(dot(a,a));}
  28. double Angle(Vector a,Vector b){return acos(dot(a,b)/Length(a)/Length(b));}
  29. double Xmult(Vector a,Vector b){return a.x*b.y-b.x*a.y;}
  30. double Area(Vector a,Vector b,Vector c){return Xmult(b-a,c-a);}
  31. int Intersec(Vector a,Vector b,Vector c,Vector d)
  32. {
  33. if(max(a.x,b.x)<min(c.x,d.x))return false;
  34. if(max(a.y,b.y)<min(c.y,d.y))return false;
  35. if(max(c.x,d.x)<min(a.x,b.x))return false;
  36. if(max(c.y,d.y)<min(a.y,b.y))return false;
  37. if(Area(c,b,a)*Area(b,d,a)<)return false;
  38. if(Area(a,d,c)*Area(d,b,c)<)return false;
  39. return true;
  40. }
  41. Vector Interpoint(Vector a,Vector b,Vector c,Vector d)
  42. {
  43. Vector u=a-c;
  44. double t=Xmult(d,u)/Xmult(b,d);
  45. return a+b*t;
  46. }
  47. Vector Normal(Vector a){return (Vector){-a.y,a.x};}
  48. double Distoline(Vector p,Vector a,Vector b)
  49. {
  50. Vector v1=b-a,v2=p-a;
  51. return fabs(Xmult(v1,v2)/Length(v1));
  52. }
  53. int Onseg(Vector p,Vector a,Vector b){return dcmp(Xmult(a-p,b-p))== && dcmp(dot(a-p,b-p))<;}
  54. #define point Vector
  55. struct Seg{point a,b;}que[];
  56. struct polygon
  57. {
  58. point ps[];
  59. int cnt;
  60. inline int inpo(point &a)
  61. {
  62. int tot=;
  63. for(int i=;i<=cnt;i++)
  64. if(Onseg(a,ps[i],ps[i%cnt+]))return ;
  65. point ray=(point){-,a.y+0.1};
  66. a.y+=0.1;
  67. for(int i=;i<=cnt;i++)
  68. tot+=Intersec(ray,a,ps[i],ps[i%cnt+]);
  69. a.y-=0.1;
  70. return tot&;
  71.  
  72. }
  73. }island[];
  74. struct near
  75. {
  76. point p;
  77. double dis;
  78. };
  79. near disps(point a,point b,point c)
  80. {
  81. if(b==c)return (near){b,Length(b-a)};
  82. Vector v1=c-b,v2=a-b,v3=a-c;
  83. if(dcmp(dot(v1,v2))<=) return (near){b,Length(v2)};
  84. if(dcmp(dot(v1,v3))>=) return (near){c,Length(v3)};
  85. Vector v=Normal(b-c);
  86. point ans=Interpoint(a,v,b,v1);
  87. return (near){ans,Length(a-ans)};
  88. }
  89. bool check(point a)
  90. {
  91. for(int i=;i<=n;i++)
  92. if(island[i].inpo(a))
  93. return true;
  94. return false;
  95. }
  96. near Find(point &p)
  97. {
  98. if(check(p)) return (near){p,};
  99. near ans1;
  100. ans1.dis=<<;
  101. for(int i=;i<=n;i++)
  102. for(int j=;j<=island[i].cnt;j++)
  103. {
  104. near get=disps(p,island[i].ps[j],island[i].ps[j%island[i].cnt+]);
  105. if(dcmp(ans1.dis-get.dis)>=) ans1=get;
  106. }
  107. ans=max(ans,ans1.dis);
  108. return ans1;
  109. }
  110. void dfs()
  111. {
  112. int front=,rear=;
  113. for(int i=;i<m;i++)
  114. que[++rear]=(Seg){temp[i],temp[i+]},Find(temp[i]);
  115. Find(temp[m]);
  116. Seg head;
  117. while(front!=rear)
  118. {
  119. head=que[front=front%MAXQ+];
  120. point p1=Find(head.a).p,p2=Find(head.b).p,l=head.a,r=head.b,mid=(l+r)/;
  121. while(Length(r-l)>1e-)
  122. {
  123. point mid=(r+l)/;
  124. if(Length(mid-p1)<Length(mid-p2)) l=mid;
  125. else r=mid;
  126. }
  127. double nowans=max(Length(l-p1),Length(l-p2));
  128. Find(l);
  129. if(ans+0.005<nowans) que[rear=rear%MAXQ+]=(Seg){head.a,mid},que[rear=rear%MAXQ+]=(Seg){mid,head.b};
  130. }
  131. }
  132. int main()
  133. {
  134. scanf("%d %d",&n,&m);
  135. for(int i=;i<=m;i++)
  136. temp[i].Read();
  137. for(int i=;i<=n;i++)
  138. {
  139. scanf("%d",&island[i].cnt);
  140. for(int j=;j<=island[i].cnt;j++)
  141. island[i].ps[j].Read();
  142. }
  143. dfs();
  144. printf("%.2lf",ans);
  145. }

bzoj1021 循环的债务

dp[i][j][k]表示第i种钱,第一个人还有j块钱,第二个人还有k块钱时的交换钞票数

然后依然是个背包

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<algorithm>
  4. #include<cstring>
  5. #include<cstdlib>
  6. #include<cmath>
  7. using namespace std;
  8. int x1,x2,x3;
  9. int cnt[][],sum[];
  10. const int m[]={,,,,,,};
  11. int f[][][];
  12. int g[];
  13. int tmp[];
  14. int gcd(int a,int b){return b?gcd(b,a%b):a;}
  15.  
  16. int main()
  17. {
  18. scanf("%d%d%d",&x1,&x2,&x3);
  19. for(int i=;i<=;i++)
  20. for(int j=;j<=;j++)
  21. {
  22. scanf("%d",&cnt[i][j]);
  23. sum[i]=sum[i]+cnt[i][j]*m[j];
  24. }
  25. int r1=sum[]-x1+x3,r2=sum[]-x2+x1;
  26. g[]=;
  27. for(int i=;i<=;i++)g[i]=gcd(g[i-],m[i]);
  28. memset(f,0x3f,sizeof(f));
  29. f[][sum[]][sum[]]=;
  30. for(int i=;i>=;i--)
  31. {
  32. int j=sum[]+sum[]+sum[];
  33. while((j-r1)%g[i])j--;
  34. for(;j>=;j-=g[i])
  35. {
  36. int k=sum[]+sum[]+sum[]-j;
  37. while((k-r2)%g[i])k--;
  38. for(;k>=;k-=g[i])
  39. {
  40. if(f[i][j][k]>)continue;
  41. f[i-][j][k]=min(f[i-][j][k],f[i][j][k]);
  42. for(int x=;x<=;x++)
  43. {
  44. int y=(x+)%,z=(x+)%;
  45. for(int xx=;xx<=cnt[x][i];xx++)
  46. for(int yy=;yy<=xx;yy++)
  47. {
  48. tmp[x]=-xx*m[i];tmp[y]=yy*m[i];z[tmp]=(xx-yy)*i[m];
  49. f[i-][j+tmp[]][k+tmp[]]=min(f[i-][j+tmp[]][k+tmp[]],f[i][j][k]+xx);
  50. }
  51.  
  52. //Invisible w
  53. for(int xx=;xx<=cnt[y][i];xx++)
  54. for(int yy=;yy<=cnt[z][i];yy++)
  55. {
  56. tmp[x]=(xx+yy)*m[i];
  57. tmp[y]=-xx*m[i];tmp[z]=-yy*m[i];
  58. f[i-][j+tmp[]][k+tmp[]]=min(f[i-][j+tmp[]][k+tmp[]],f[i][j][k]+xx+yy);
  59. }
  60. }
  61. }
  62. }
  63. }
  64. int ans=f[][r1][r2];
  65. printf(ans>=?"impossible":"%d",ans);
  66. return ;
  67. }

bzoj1022 小约翰的游戏

一看这不是Nim吗然后交了个Nim上去

发现竟然跟Nim是相反的

然后出现了一个新的小细节:如果有偶数堆,每堆一个石子,先手会赢

博弈论的题竟然不是Alice和Bob,好评

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<cstdlib>
  4. #include<cmath>
  5. #include<cstring>
  6. #include<algorithm>
  7. using namespace std;
  8. int x,sum,flag;
  9. int T,n;
  10. int main()
  11. {
  12. scanf("%d",&T);
  13. while(T--)
  14. {
  15. sum=,flag=;
  16. scanf("%d",&n);
  17. for(int i=;i<=n;i++)
  18. {
  19. scanf("%d",&x);
  20. sum^=x;
  21. if(x!=)flag=;
  22. }
  23. if((sum== && flag==) || (sum!= && flag==))printf("John\n");
  24. else printf("Brother\n");
  25. }
  26. return ;
  27. }

bzoj1023 仙人掌图

很大意义上来说这不算仙人掌的题

搞成一棵树找直径

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<cstdlib>
  4. #include<cmath>
  5. #include<cstring>
  6. #include<algorithm>
  7. using namespace std;
  8. int first[],to[],next[],fa[],cnt;
  9. int ind,dfn[],low[],depth[],q[];
  10. int a[];
  11. int ans;
  12. int f[];
  13. int n,m;
  14. inline int read()
  15. {
  16. int x=,f=;
  17. char ch=getchar();
  18. for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-f;
  19. for(;isdigit(ch);ch=getchar())x=*x+ch-'';
  20. return x*f;
  21. }
  22. inline void add(int u,int v)
  23. {
  24. to[++cnt]=v;
  25. next[cnt]=first[u];
  26. first[u]=cnt;
  27. }
  28. inline void dp(int x,int y)
  29. {
  30. int cnt=depth[y]-depth[x]+,head=,tail=,i;
  31. for (i=y; i!=x; i=fa[i]) a[cnt--]=f[i]; a[]=f[x];
  32. cnt=depth[y]-depth[x]+; q[]=;
  33. for (i=; i<=cnt; i++) a[i+cnt]=a[i];
  34. for (i=; i<=cnt+(cnt>>); i++){
  35. if (i-q[head]>(cnt>>)) head++;
  36. ans=max(ans,a[i]+i+a[q[head]]-q[head]);
  37. while (head<=tail && a[i]-i>=a[q[tail]]-q[tail]) tail--; q[++tail]=i;
  38. }
  39. for (i=; i<=cnt; i++) f[x]=max(f[x],a[i]+min(i-,cnt-i+));
  40. }
  41. inline void Tarjan_dfs(int x)
  42. {
  43. dfn[x]=low[x]=++ind;
  44. for(int i=first[x];i;i=next[i])
  45. {
  46. if(to[i]==fa[x])continue;
  47. if(!dfn[to[i]])
  48. {
  49. fa[to[i]]=x;
  50. depth[to[i]]=depth[x]+;
  51. Tarjan_dfs(to[i]);
  52. }
  53. low[x]=min(low[x],low[to[i]]);
  54. if(low[to[i]]>dfn[x])
  55. {
  56. ans=max(ans,f[to[i]]+f[x]+);
  57. f[x]=max(f[x],f[to[i]]+);
  58. }
  59. }
  60. for(int i=first[x];i;i=next[i])
  61. if(fa[to[i]]!=x && dfn[x]<dfn[to[i]])dp(x,to[i]);
  62. }
  63. int main()
  64. {
  65. n=read(); m=read(); int i;
  66. for (i=; i<=m; i++)
  67. {
  68. int tmp=read(),last=;
  69. while (tmp--){
  70. int x=read(); if (last){ add(x,last); add(last,x); } last=x;
  71. }
  72. }
  73. Tarjan_dfs();
  74. printf("%d\n",ans);
  75. return ;
  76. }

bzoj1024 生日快乐

爆搜,每次把蛋糕砍成两块

  1. #include <iostream>
  2. #include <algorithm>
  3. #include <cstring>
  4. #include <cstdio>
  5. #include <cmath>
  6. using namespace std;
  7. double s;
  8. double dfs(double x,double y,int n)
  9. {
  10. if(n==)
  11. {
  12. return max(x/y,y/x);
  13. }
  14. double ans=1e10;
  15. for(int i=;i<=n/;i++)
  16. {
  17. double tx=x*i/n,ty=y*i/n;
  18. ans=min(ans,max(dfs(tx,y,i),dfs(x-tx,y,n-i)));
  19. ans=min(ans,max(dfs(x,ty,i),dfs(x,y-ty,n-i)));
  20. }
  21. return ans;
  22. }
  23. int x,y,n;
  24. int main()
  25. {
  26. scanf("%d%d%d",&x,&y,&n);
  27. s=(x*y)/n;
  28. printf("%lf",dfs(x,y,n));
  29. return ;

bzoj1025

简单推一下就会发现跟博弈论鸡毛关系都没有

题目变成了

“求和为n的数列的最小公倍数种数”

然后随便D一下

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<cstdlib>
  4. #include<algorithm>
  5. #include<cmath>
  6. #include<cstring>
  7. #define ll long long
  8. using namespace std;
  9. int n;
  10. int check[],pri[],cnt;
  11. ll dp[][],res;
  12. void laji()
  13. {
  14. for(int i=;i<=;i++)
  15. {
  16. if(!check[i])pri[++cnt]=i;
  17. for(int j=;j<=cnt;j++)
  18. {
  19. if(i*pri[j]>)break;
  20. check[i*pri[j]]=;
  21. if(i%pri[j]==)break;
  22. }
  23. }
  24. }
  25. int main()
  26. {
  27. scanf("%d",&n);
  28. laji();
  29. dp[][]=;
  30. for(int i=;i<=cnt;i++)
  31. {
  32. for(int j=;j<=n;j++)dp[i][j]=dp[i-][j];
  33. for(int j=pri[i];j<=n;j*=pri[i])
  34. for(int k=;k<=n-j;k++)dp[i][k+j]+=dp[i-][k];
  35. }
  36. for(int i=;i<=n;i++)res+=dp[cnt][i];
  37. cout<<res;
  38. }

bzoj1000~1025的更多相关文章

  1. UVA - 1025 A Spy in the Metro[DP DAG]

    UVA - 1025 A Spy in the Metro Secret agent Maria was sent to Algorithms City to carry out an especia ...

  2. Light OJ 1025 - The Specials Menu(动态规划-区间dp)

    题目链接:http://www.lightoj.com/volume_showproblem.php?problem=1025 题目大意:一串字符, 通过删除其中一些字符, 能够使这串字符变成回文串. ...

  3. HDU 1025 Constructing Roads In JGShining's Kingdom(求最长上升子序列nlogn算法)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1025 解题报告:先把输入按照r从小到大的顺序排个序,然后就转化成了求p的最长上升子序列问题了,当然按p ...

  4. HDU 1025 Constructing Roads In JGShining's Kingdom(二维LIS)

    Constructing Roads In JGShining's Kingdom Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65 ...

  5. PAT乙级 1025. 反转链表 (25)

    1025. 反转链表 (25) 时间限制 300 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 作者 CHEN, Yue 给定一个常数K以及一个单链表L,请 ...

  6. uva 1025,城市的间谍

    题目链接:https://uva.onlinejudge.org/external/10/1025.pdf 题意: 地铁是线性的,有n个站,编号(1~n),M1辆从左至右的车,和M2辆从右至左的车,发 ...

  7. 【BZOJ】【1025】【SCOI2009】游戏

    DP/整数拆分 整个映射关系可以分解成几个循环(置换群的预备知识?),那么总行数就等于各个循环长度的最小公倍数+1(因为有个第一行的1~N).那么有多少种可能的排数就等于问有多少种可能的最小公倍数. ...

  8. bzoj 1025 [SCOI2009]游戏(置换群,DP)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=1025 [题意] 给定n,问1..n在不同的置换下变回原序列需要的不同排数有多少种. [ ...

  9. PAT-乙级-1025. 反转链表 (25)

    1025. 反转链表 (25) 时间限制 300 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 作者 CHEN, Yue 给定一个常数K以及一个单链表L,请 ...

随机推荐

  1. Android 适配(一)

    一.Android适配基础参数 1.常见分辨率(px)      oppx 2340x1080      oppR15 2280x1080      oppor11sp 2160*1080       ...

  2. WPF 支持集合绑定的控件

    WPF 支持集合绑定的控件 ListBox ComboBox ListView DataGrid

  3. 【BZOJ1226】[SDOI2009]学校食堂Dining 状压DP

    [BZOJ1226][SDOI2009]学校食堂Dining Description 小F 的学校在城市的一个偏僻角落,所有学生都只好在学校吃饭.学校有一个食堂,虽然简陋,但食堂大厨总能做出让同学们满 ...

  4. 【python】-- Socket粘包问题 ,解决粘包的几种方法、socket文件下载,md5值检验

    上一篇随笔:“socket 接收大数据”,在win系统上能够运行,并且解决了大数据量的数据传输出现的问题,但是运行在linux系统上就会出现如下图所示的情况: 就是服务端两次发送给客户端的数据(第一次 ...

  5. linux 字符驱动

    1 结构体说明:     struct cdev {         struct kobject kobj;          // 每一个 cdev 都是一个 kobject         st ...

  6. 安装Nginx 及使用

    1.下载 Nginx wget http://nginx.org/download/nginx-1.10.3.tar.gz   (稳定版) 2.提前下载好依赖包 openssl.zlib.pcre p ...

  7. Nodejs课堂笔记-第三课 构建一个nodejs的Docker镜像

    本文由Vikings(http://www.cnblogs.com/vikings-blog/) 原创,转载请标明.谢谢! 因为一直做Linux有关的开发工作,所以不习惯在Windows平台编译和测试 ...

  8. Struts2学习总结(完整版)

    一.搭建struts2环境 1.jar包的导入 主要是到 解压其中的一个工程,得到里面lib下包含的jar包 把这里的所有的jar包拷贝到项目的 WEB-INF目录下的lib文件夹下面. 2.配置st ...

  9. 添加启动项及常用Windows+R

    常用Windows+R services.msc---本地服务设置 msconfig---系统配置实用程序 mspaint--------画图板 notepad--------打开记事本 Nslook ...

  10. 查看django的安装路径

    查看django的安装路径 pip3 show django