去冬令营转了一圈发现自己比别人差根源在于刷题少,见过的套路少(>ω<)

于是闲来无事把历年省选题做了一些

链接放的都是洛谷的,bz偷懒放的也是链接

AM.T1 奇怪的背包

Problem

HAOI-2018奇怪的背包

Solution

暴力 \(60\),加上送的 \(10\) 有 \(70\) ,暴力进队

首先在模意义下倍数能表达的东西……裴蜀定理!即 \(\{kx\bmod p\}=\{k\cdot \gcd(x,p)\bmod p\}\),所以输入的 \(V_i\) 可以先与 \(P\) 取个 \(\gcd\)

然后发现这样处理之后所有的 \(V_i|P\),即都是 \(P\) 的因子,而 \(P\leq 10^9\) 时,不同的因子最多大约有 \(2^{10}\) 个。

所以可以很快列出方程:

\[f[i][j] += f[i-1][j]\\
f[i][\gcd(j,V_i)]+=(2^{c_i}-1)\cdot f[i][j]
\]

其中 \(f[i][j]\) 表示考虑前 \(i\) 个因子且选取数的 \(\gcd\) 为 \(j\) 时的方案数,由于这个状态两维是同阶的,所以计算次数在 \(10^6\) 左右

最后统计答案,考虑统计 \(x\) 的答案,为 \(\sum_{d|x}g[d]\),其中 \(g[d]\) 表示选择中 \(\gcd\) 为 \(d\) 的方案总数,由 \(f\) 可得

而若 \(d\not | P\),则 \(g[d]=0\) 不需要考虑,所以只需要考虑 \(\sum_{d|\gcd(x,P)}g[d]\),而 \(\gcd(x,P)\) 又是 \(P\) 的因子了,可以预处理

Code

偷懒用了 \(map\)

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. typedef long long ll;
  4. template <typename _tp> inline void read(_tp&x){
  5. char c11=getchar(),ob=0;x=0;
  6. while(c11!='-'&&!isdigit(c11))c11=getchar();if(c11=='-')ob=1,c11=getchar();
  7. while(isdigit(c11))x=x*10+c11-'0',c11=getchar();if(ob)x=-x;
  8. }
  9. const int N = 2047, p = 1e9+7;
  10. int bs[N],tp;
  11. int c[N],f[N][N],g[N];
  12. int n,Q,P;
  13. inline void pls(int&A,const int&B) {A += B; if(A >= p) A -= p;}
  14. inline int qpow(int A,int B){
  15. int res = 1; while(B){
  16. if(B&1) res = (ll)res * A%p;
  17. A = (ll)A * A%p, B >>= 1;
  18. }return res;
  19. }
  20. map <int,int> mp;
  21. int main(){
  22. read(n),read(Q),read(P);
  23. for(int i=1;i*i<=P;++i)
  24. if(P % i == 0)
  25. bs[++tp] = i, bs[++tp] = P/i;
  26. if(bs[tp] == bs[tp-1]) --tp;
  27. sort(bs+1,bs+tp+1);
  28. for(int i=1;i<=tp;++i)
  29. mp[bs[i]] = i;
  30. for(int i=1,x;i<=n;++i){
  31. read(x), x = __gcd(x,P);
  32. ++c[mp[x]];
  33. }
  34. f[0][tp] = 1;
  35. for(int i=1;i<=tp;++i)
  36. for(int j=1;j<=tp;++j){
  37. f[i][j] = f[i-1][j];
  38. pls(f[i][mp[__gcd(bs[i],bs[j])]], (ll)f[i-1][j]*(qpow(2,c[i])-1)%p);
  39. }
  40. for(int i=1;i<=tp;++i)
  41. g[i] = f[tp][i];
  42. for(int i=tp;i;--i)
  43. for(int j=i+1;j<=tp;++j)
  44. if(bs[j] % bs[i] == 0)
  45. pls(g[j],g[i]);
  46. int x;
  47. while(Q--){
  48. read(x), x = __gcd(x,P);
  49. printf("%d\n",g[mp[x]]);
  50. }
  51. return 0;
  52. }

AM.T2 反色游戏

Problem

HAOI-2018反色游戏

Solution

首先 \(70\) 可以动态线性基……

然后一个环同时取反影响不变,所以可以找出一棵生成树

进一步的,生成树上的边全部线性无关,而非树边取任意状态都可以在生成树上找到一个对应状态,设非树边有 \(t\) 条,答案为 \(2^t\)

然后题目要求删除每个点后的答案……明显和HNOI2012矿场搭建类似求出点双分别维护即可

如果没想全所有情况可能会很难调

Code

  1. #include <bits/stdc++.h>
  2. inline void cmin(int&A,const int&B) {if(A > B) A = B;}
  3. inline void read(int&x){
  4. char c11=getchar();x=0;while(!isdigit(c11))c11=getchar();
  5. while(isdigit(c11))x=x*10+c11-'0',c11=getchar();
  6. }
  7. const int N = 101000, p = 1e9+7;
  8. struct Edge{int v,nxt;} a[N+N];
  9. int head[N],dfn[N],low[N];
  10. int id[N],blk[N],cut[N],fuck[N],di[N];
  11. int sz_blk[N],son_blk[N];
  12. int deg[N],bin[N];char s[N];
  13. int n,m,T,_,O,dfc;
  14. inline int qm(int x) {return x < p ? x : x - p;}
  15. inline void ad(){
  16. static int x,y; read(x), read(y);
  17. a[++_].v = y, a[_].nxt = head[x], head[x] = _, ++deg[x];
  18. a[++_].v = x, a[_].nxt = head[y], head[y] = _, ++deg[y];
  19. }
  20. void dfs(int x){
  21. dfn[x] = low[x] = ++dfc;
  22. id[x] = O, sz_blk[x] = blk[x];
  23. di[x] = (x != O);
  24. for(int i=head[x];i;i=a[i].nxt){
  25. if(!dfn[a[i].v]){
  26. dfs(a[i].v);
  27. cmin(low[x], low[a[i].v]);
  28. sz_blk[x] += sz_blk[a[i].v];
  29. if(dfn[x] <= low[a[i].v]){
  30. ++di[x];
  31. son_blk[x] += son_blk[a[i].v];
  32. if(x != O) cut[x] = 1;
  33. if(sz_blk[a[i].v]&1) ++fuck[x];
  34. }
  35. }else cmin(low[x], dfn[a[i].v]);
  36. }
  37. if(x == O and a[head[x]].nxt) cut[x] = 1;
  38. }
  39. int main(){
  40. bin[0] = 1;
  41. for(int i=1;i<N;++i) bin[i] = qm(bin[i-1] << 1);
  42. read(T);
  43. while(T--){
  44. read(n),read(m);
  45. for(int i=1;i<=m;++i) ad();
  46. scanf("%s",s+1);
  47. for(int i=1;i<=n;++i) blk[i] = s[i] - '0';
  48. int con = 0, sum = 0;
  49. for(int i=1;i<=n;++i)
  50. if(!dfn[i]){
  51. O = i, dfs(i), ++con;
  52. sum += (sz_blk[i] & 1);
  53. }
  54. printf("%d",sum ? 0 : bin[m-n+con]);
  55. for(int x=1;x<=n;++x){
  56. int res = bin[m - n + con - deg[x] + di[x]];
  57. if(fuck[x]) res = 0;
  58. if(sz_blk[id[x]] - son_blk[x] - blk[x] & 1) res = 0;
  59. if(sum - (sz_blk[id[x]] & 1)) res = 0;
  60. printf(" %d",res);
  61. }
  62. dfc = _ = 0;
  63. for(int i=1;i<=n;++i){
  64. head[i] = sz_blk[i] = son_blk[i] = fuck[i] = di[i] = 0;
  65. id[i] = deg[i] = blk[i] = dfn[i] = low[i] = cut[i] = 0;
  66. }
  67. putchar(10);
  68. }
  69. return 0;
  70. }

AM.T3 字串覆盖

Problem

HAOI-2018字串覆盖

Solution

直接想还是很难的……

但是看到部分分那么具有提示性,肯定是拼接程序

对于 \(r-l\) 比较大的时候:建出后缀数组,可以找到一个匹配区间,建出主席树每次贪心选取

对于 \(r-l\) 比较小的时候:使用 \(O((r-l)n)\) 的空间预处理一下即可

Code

我确信我写出了一份完美的代码,只是这里地方太小,放不下 懒得写

PM.T1 苹果树

Problem

HAOI-2018苹果树

Solution

这题很坑的一点是 \(p\) 不为质数不能直接除

然后二叉树n≤2000随机等字样时刻提醒着要 \(O(n^2)\) Dp

为了考虑合并两个子树时新产生的距离,要维护一个深度和数组 \(g[i]\)

为了考虑合并两个子树时的带权关系,要维护一个生成树种类数组 \(h[i]\)

然后要求答案,设 \(f[i]\) 表示当前子树有 \(i\) 个节点时的期望距离和

首先 \(h[i]=i!\),因为第 \(i\) 个点有 \(i\) 种放置方法

\[g[i]=i\cdot h[i]+\sum_{L+R+1=i}\binom {i-1}{L}(g[L]h[R]+g[R]h[L])
\]

\[f[i]=\sum_{L+R+1=i}\binom {i-1}{L}\bigl[f[L]h[R]+f[R]h[L]+g[R]h[L](L+1)+g[L]h[R](R+1)\bigr]
\]

时间复杂度 \(O(n^2)\)

Code

  1. #include <cstdio>
  2. typedef long long ll;
  3. const int N = 2017;
  4. int c[N][N],fac[N],f[N],g[N];
  5. int n,p;
  6. int main(){
  7. scanf("%d%d",&n,&p);
  8. fac[0] = c[0][0] = 1;
  9. for(int i=1;i<=n;++i){
  10. fac[i] = (ll)fac[i-1] * i%p;
  11. c[i][0] = 1;
  12. for(int j=1;j<=i;++j)
  13. c[i][j] = (c[i-1][j-1] + c[i-1][j])%p;
  14. }
  15. g[1] = 1;
  16. for(int i=2;i<=n;++i){
  17. g[i] = (ll)fac[i] * i%p;
  18. for(int j=0;j<i;++j){
  19. int L = j, R = i-j-1;
  20. g[i] = (g[i] + (ll)c[i-1][j] * (((ll)g[L] * fac[R] + (ll)g[R] * fac[L])%p))%p;
  21. f[i] = (f[i] + (ll)c[i-1][j] * (((ll)f[L] * fac[R] + (ll)g[R] * fac[L]%p * (L+1))%p))%p;
  22. f[i] = (f[i] + (ll)c[i-1][j] * (((ll)f[R] * fac[L] + (ll)g[L] * fac[R]%p * (R+1))%p))%p;
  23. }
  24. }
  25. printf("%d\n",f[n]);
  26. return 0;
  27. }

PM.T2 染色

Problem

HAOI-2018染色

Solution

好吧,一开始看错题了以为是道累加贡献的水题……然而也不难

由于直接计算不方便,计算 \(g(i)\) 表示恰好出现 \(S\) 次的颜色有至少 \(i\) 种,\(f(i)\) 表示恰好 \(i\) 种

\[g(i)=\binom mi\frac {P_n^{iS}}{(S!)^i}(m-i)^{n-iS}
\]

\[g(i)=\sum_{j=i}^m\binom ji f(j)\Leftrightarrow f(i)=\sum_{j=i}^m(-1)^{j-i}\binom jig(j)
\]

最后答案为 \(\sum_i w_if_i\),可以 \(ntt\) 加速(不用再把 \(g(j)\) 拆开了,直接求出 \(g(x)\) 后再与二项式系数做卷积)

Code

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. typedef long long ll;
  4. inline void read(int&x){
  5. char c11=getchar();x=0;while(!isdigit(c11))c11=getchar();
  6. while(isdigit(c11))x=x*10+c11-'0',c11=getchar();
  7. }
  8. const int N = 10001000, M = 301000, p = 1004535809, G = 3;
  9. int rev[M];
  10. inline int qm(const int&x) {return x < p ? x : x-p;}
  11. inline int qpow(int A,int B){
  12. int res = 1; while(B){
  13. if(B&1) res = (ll)res * A%p;
  14. A = (ll)A * A%p, B >>= 1;
  15. }return res;
  16. }
  17. void ntt(int*a,int n,int sgn){
  18. for(int i=1;i<n;++i) if(i < rev[i]) swap(a[i],a[rev[i]]);
  19. for(int i=1;i<n;i<<=1){
  20. int gn = qpow(G, (p-1)/(i<<1));
  21. for(int j=0;j<n;j+=(i<<1)){
  22. int g = 1;
  23. for(int k=0;k<i;++k,g=(ll)g*gn%p){
  24. int x = a[j+k], y = (ll)g*a[j+k+i]%p;
  25. a[j+k] = qm(x+y), a[j+k+i] = qm(x-y+p);
  26. }
  27. }
  28. }
  29. if(!sgn){
  30. int iv = qpow(n,p-2); reverse(a+1,a+n);
  31. for(int i=0;i<n;++i) a[i] = (ll)a[i] * iv%p;
  32. }
  33. }
  34. void Conv(int*arr,int*brr,int n){
  35. int nn = 1, len = 0;
  36. while(nn<n+n) nn <<= 1, ++len;
  37. for(int i=1;i<nn;++i) rev[i] = (rev[i>>1]>>1)|((i&1)<<(len-1));
  38. ntt(arr,nn,1),ntt(brr,nn,1);
  39. for(int i=0;i<nn;++i) arr[i] = (ll)arr[i]*brr[i]%p;
  40. ntt(arr,nn,0);
  41. }
  42. int w[M],fac[N],inv[N],g[M],brr[M];
  43. int n,m,S,L;
  44. inline int P(int nn,int mm) {return (ll)fac[nn] * inv[nn-mm]%p;}
  45. inline int C(int nn,int mm) {return (ll)fac[nn] * inv[mm]%p * inv[nn-mm]%p;}
  46. int main(){
  47. read(n),read(m),read(S); L = min(m,n/S);
  48. for(int i=0;i<=m;++i) read(w[i]);
  49. fac[0] = inv[0] = 1;
  50. int MX = max(n,m);
  51. for(int i=1;i<=MX;++i) fac[i] = (ll)fac[i-1] * i%p;
  52. inv[MX] = qpow(fac[MX], p-2);
  53. for(int i=MX;i;--i) inv[i-1] = (ll)inv[i] * i%p;
  54. for(int i=0;i<=L;++i)
  55. g[i] = (ll)C(m,i) * P(n,i*S)%p * qpow(qpow(fac[S],i),p-2)%p * qpow(m-i,n-i*S)%p;
  56. for(int i=0;i<=m;++i){
  57. g[i] = (ll)g[i] * fac[i]%p;
  58. brr[i] = (i&1? p-inv[i] : inv[i]);
  59. }
  60. reverse(brr,brr+m+1);
  61. Conv(g,brr,m);
  62. int Ans = 0;
  63. for(int i=0;i<=m;++i)
  64. Ans = (Ans + (ll)w[i] * g[i+m]%p * inv[i])%p;
  65. printf("%d\n",Ans);
  66. return 0;
  67. }

题解-HAOI2018全套的更多相关文章

  1. 题解-Codeforces1106全套

    因为参加完wc后心情很差,而且在广州过年没Ubuntu,所以就没打这场比赛了,结果这套题全部1A了,现在看来真是错失良机 结果这场不计rating 今天是除夕,大家节日快乐 A. Lunar New ...

  2. 题解 [HAOI2018]反色游戏

    题目传送门 题目大意 给出一个 \(n\) 个点 \(m\) 条无向边的图,每个点都有一个 \(\in [0,1]\) 的权值,每次可以选择一条边,然后将该边相连两点权值异或上 \(1\).问有多少种 ...

  3. HAOI2018 简要题解

    这套题是 dy, wearry 出的.学长好强啊,可惜都 \(wc\) 退役了.. 话说 wearry 真的是一个计数神仙..就没看到他计不出来的题...每次考他模拟赛总有一两道毒瘤计数TAT 上午的 ...

  4. 【题解】[HAOI2018]染色(NTT+容斥/二项式反演)

    [题解][HAOI2018]染色(NTT+容斥/二项式反演) 可以直接写出式子: \[ f(x)={m \choose x}n!{(\dfrac 1 {(Sx)!})}^x(m-x)^{n-Sx}\d ...

  5. 【qboi冲刺NOIP2017复赛试题4】 全套题目+题解+程序

    作为一个好人(验题人),我给大家奉上下这套题的题解,并且预祝大家这套题能够AK: T1题面:Alice现在有n根木棍,他们长度为1,2,3....n,Bob想把某一些木棍去掉,使得Alice剩下的木棍 ...

  6. 【题解】HAOI2018染色

    好坑啊不开心…… 其实这题的想法还是比较简单粗暴的.题目明示恰好xxx,显然排除斜率二分这个玩意儿,那么不就只剩下容斥了嘛…… 令 \(A_{x}\) 为恰好出现了 \(S\) 次的至少有 \(x\) ...

  7. POJ1389:Area of Simple Polygons——扫描线线段树题解+全套代码注释

    http://poj.org/problem?id=1389 题面描述在二维xy平面中有N,1 <= N <= 1,000个矩形.矩形的四边是水平或垂直线段.矩形由左下角和右上角的点定义. ...

  8. haoi2018奇怪的背包题解

    题目传送门:https://www.lydsy.com/JudgeOnline/problem.php?id=5302 对于一个物品,设它体积为v,那么,在背包参数为p的情况下,它能达到gcd(v,p ...

  9. HAOI2018简要题解

    大概之后可能会重写一下,写的详细一些? Day 1 T1 简单的背包:DP 分析 可以发现,如果选出了一些数,令这些数的\(\gcd\)为\(d\),那么这些数能且仅能组合成\(\gcd(d,P)\) ...

随机推荐

  1. 不能完整读取txt文件问题

    txt文件内容 5 1.3 0.4 3.4 -1.7 16.7 0.89 14.17 4.8 1.34 0.42 3.36 -2 16.2 0.9 14.8 4.9 1.30 0.37 3.51 -1 ...

  2. Bootstrap起步

    Bootstrap 是最受欢迎的 HTML.CSS 和 JS 框架,用于开发响应式布局.移动设备优先的 WEB 项目. Bootstrap 插件全部依赖 jQuery 请注意,Bootstrap 的所 ...

  3. icpc南宁站赛后总结

    11月24号,我们经过26个小时的火车来到了广西南宁,一场漫长的过程. 24号晚到达南宁,做地铁到达学校,找到住的地方,南宁的天真是让人无奈. 25号,上午去广西大学体育馆报道,然后回去好好整理了一下 ...

  4. AirPods 2 & Android

    AirPods 2 & Android AirBattery https://play.google.com/store/apps/details?id=friedrich.georg.air ...

  5. SpringBoot配置MySql数据库和Druid连接池

    1.pom文件增加相关依赖 <dependency> <groupId>mysql</groupId> <artifactId>mysql-connec ...

  6. 数据分析之Numpy

    Numpy numpy.array:将数组转换成向量 numpy.array([,,,]) 转化成1维向量 numpy.array([[,,],[,,],[,,]]) 转换成二维向量 vector = ...

  7. 【kafka】Java连接出现Connection refused: no further information的解决方法

    在Linux机器(ip:10.102.16.203)安装完kafka(参考:kafka的安装及使用),在windows上使用Java接口访问服务时(参考:Java实现Kafka的生产者.消费者),报异 ...

  8. 搭建alpine仓库 提供apk包

    搭建alpine私有仓库从官方拉取alpine所有的包 wget -r -np -nH http://nl.alpinelinux.org/alpine/v3.5/main/x86_64/ wget ...

  9. Flask 构建微电影视频网站(七)

    电影模块实现 上映预告 @home.route("/animation/") def animation(): """ 首页轮播动画 "&q ...

  10. NOIP 2019游记

    Update on 2019.4.20 禁赛预定