• 2019ICPC南京站


    A

    A Hard Problem

    题意:给定一个正整数 n ,你需要找出最小整数 k,满足:从{1,2,⋯,n}中任意选择长度为k的子集,存在两个不同的整数 u,v∈T, 且 u 是 v 的因数。

    思路:打表找规律 k = \left \lceil n/2 \right \rceil + 1

    1. #include
    2. #define ios ios::sync_with_stdio(0),cin.tie(0)
    3. #define PII pair
    4. typedef long long ll;
    5. const int N=1e8+10;
    6. const int inf=0x3f3f3f3f;
    7. using namespace std;
    8. void solve()
    9. {
    10. int n;
    11. cin>>n;
    12. cout<<(n+3)/2<<'\n';
    13. }
    14. signed main()
    15. {
    16. //freopen("input.txt","r",stdin);
    17. //freopen("output.txt","w",stdout);
    18. ios;
    19. // get();
    20. // cout<
    21. int _t=1;
    22. cin>>_t;
    23. while(_t--) solve();
    24. system("pause");
    25. return 0;
    26. }

    C

    Digital Path

    题意:给定一个n*m的数字矩阵,从入度为0的点出发,每次操作只能向上下左右且增值为1的格子移动,终点为出度为0的点。求长度大于等于4的路径个数。

    思路:先算出每个点的出度入度,从入度为0的开始bfs,更新方案数。

    f[i][j][x]表示到达点(i, j)路径长度为x的方案数,特别的f[i][j][4]表示到达点(i, j)路径长度大于等于4的方案数。更新方式如下:

    f[nx][ny][2] += f[x][y][1]

    f[nx][ny][3] += f[x][y][2]

    f[nx][ny][4] += f[x][y][3] + f[x][y][4]

    1. #include
    2. #define ios ios::sync_with_stdio(0),cin.tie(0)
    3. #define PII pair
    4. typedef long long ll;
    5. const int N=1010;
    6. const int inf=0x3f3f3f3f;
    7. const int mod=1e9+7;
    8. using namespace std;
    9. int n,m;
    10. int a[N][N];
    11. int in[N][N],out[N][N];
    12. int f[N][N][5];
    13. int dir[4][2]={1,0,-1,0,0,1,0,-1};
    14. void bfs()
    15. {
    16. queueint,int>>q;
    17. for(int i=1;i<=n;i++)
    18. for(int j=1;j<=m;j++)
    19. if(in[i][j]==0)
    20. {
    21. q.push({i,j});
    22. f[i][j][1]=1;
    23. }
    24. while(q.size())
    25. {
    26. int x=q.front().first,y=q.front().second;
    27. q.pop();
    28. for(int k=0;k<4;k++)
    29. {
    30. int nx=x+dir[k][0],ny=y+dir[k][1];
    31. if(nx<1||nx>n||ny<1||ny>m) continue;
    32. if(a[nx][ny]==a[x][y]+1)
    33. {
    34. f[nx][ny][2]=(f[nx][ny][2]%mod+f[x][y][1])%mod;
    35. f[nx][ny][3]=(f[nx][ny][3]%mod+f[x][y][2])%mod;
    36. f[nx][ny][4]=((f[nx][ny][4]%mod+f[x][y][3]%mod)%mod+f[x][y][4]%mod)%mod;
    37. in[nx][ny]--;
    38. if(in[nx][ny]==0) q.push({nx,ny});
    39. }
    40. }
    41. }
    42. }
    43. void solve()
    44. {
    45. cin>>n>>m;
    46. for(int i=1;i<=n;i++)
    47. for(int j=1;j<=m;j++)
    48. cin>>a[i][j];
    49. for(int i=1;i<=n;i++)
    50. for(int j=1;j<=m;j++)
    51. for(int k=0;k<4;k++)
    52. {
    53. int nx=i+dir[k][0],ny=j+dir[k][1];
    54. if(nx<1||nx>n||ny<1||ny>m) continue;
    55. if(a[nx][ny]==a[i][j]+1) out[i][j]++;
    56. else if(a[nx][ny]==a[i][j]-1) in[i][j]++;
    57. }
    58. bfs();
    59. int ans=0;
    60. for(int i=1;i<=n;i++)
    61. for(int j=1;j<=m;j++)
    62. if(out[i][j]==0) ans=(ans%mod+f[i][j][4])%mod;
    63. cout<'\n';
    64. }
    65. signed main()
    66. {
    67. //freopen("input.txt","r",stdin);
    68. //freopen("output.txt","w",stdout);
    69. ios;
    70. int _t=1;
    71. //cin>>_t;
    72. while(_t--) solve();
    73. system("pause");
    74. return 0;
    75. }

    H

    Prince and Princess

    题意:

    有n个房间,每个房间有一个人,他们知道任一个人在哪个房间,其中公主在某一房间.你可以问任一房间的人下列三个问题之一:①你是谁;②某个房间里的人是谁;③公主在哪个房间.

    这n个人可分为三类,说真话、说假话、可能说真话也可能说假话,分别有a , b , c( 0 < a , b , c < 2e5 )人.至少问几次才能确定公主在哪个房间.若无法确定,输出"NO";若可以确定,输出"YES",下一行输出最小询问次数.

    思路:考虑最坏情况,开始问的(b+c)个人都说假话,都回答错误答案A,再接着问(b+c)个人都说真话,都回答答案B,此时两个答案选择人数相同;再多问一个人,就可以区分出哪个是真话。所以至少需要问a+b+a+b+1=2(a+b)+1次,当总人数a+b+c >= 2(b+c)+1时,即a>=b+c+1时,输出YES。注意需要特判a=1 b=0 c=0时,只有公主一人时不需要询问。

    1. #include
    2. #define ios ios::sync_with_stdio(0),cin.tie(0)
    3. #define PII pair
    4. typedef long long ll;
    5. const int N=1e6+10;
    6. const int inf=0x3f3f3f3f;
    7. using namespace std;
    8. int a,b,c;
    9. void solve()
    10. {
    11. cin>>a>>b>>c;
    12. if(b+c>=a) cout<<"NO\n";
    13. else
    14. {
    15. cout<<"YES\n";
    16. if(a==1&&b==0&&c==0) cout<<0<<'\n';
    17. else if(b==0&&c==0) cout<<1<<'\n';
    18. else cout<<2*(b+c)+1<<'\n';
    19. }
    20. }
    21. signed main()
    22. {
    23. //freopen("input.txt","r",stdin);
    24. //freopen("output.txt","w",stdout);
    25. ios;
    26. int _t=1;
    27. //cin>>_t;
    28. while(_t--) solve();
    29. system("pause");
    30. return 0;
    31. }

    K

    Triangle

    题意:给定三角形三个顶点的坐标,给定点p,在三角形上找一点q的坐标,使得pq可以平分三角形面积。若p点不在三角形上时输出-1.

    思路:分类讨论,讨论p在哪条边上,更靠近边的哪个顶点,在对应的边上二分求点q

    1. #include
    2. #define ios ios::sync_with_stdio(0),cin.tie(0)
    3. #define PII pair
    4. typedef long long ll;
    5. const int N=1e6+10;
    6. const int inf=0x3f3f3f3f;
    7. const double eps=1e-7;
    8. using namespace std;
    9. inline double sqr(double x){return x*x;}
    10. int sgn(double x){
    11. if(fabs(x) < eps)return 0;
    12. if(x < 0)return -1;
    13. else return 1;
    14. }
    15. struct Point{
    16. double x,y;
    17. Point(){}
    18. Point(double _x,double _y){
    19. x = _x;
    20. y = _y;
    21. }
    22. void input(){
    23. scanf("%lf%lf",&x,&y);
    24. }
    25. Point operator -(const Point &b)const{
    26. return Point(x-b.x,y-b.y);
    27. }
    28. //叉积
    29. double operator ^(const Point &b)const{
    30. return x*b.y - y*b.x;
    31. }
    32. //点积
    33. double operator *(const Point &b)const{
    34. return x*b.x + y*b.y;
    35. }
    36. //返回两点的距离
    37. double distance(Point p){
    38. return hypot(x-p.x,y-p.y);
    39. }
    40. Point operator +(const Point &b)const{
    41. return Point(x+b.x,y+b.y);
    42. }
    43. Point operator *(const double &k)const{
    44. return Point(x*k,y*k);
    45. }
    46. };
    47. struct Line{
    48. Point s,e;
    49. Line(){}
    50. Line(Point _s,Point _e){
    51. s = _s;
    52. e = _e;
    53. }
    54. // 点在线段上的判断
    55. bool pointonseg(Point p){
    56. return sgn((p-s)^(e-s)) == 0 && sgn((p-s)*(p-e)) <= 0;
    57. }
    58. };
    59. Point mid_(Point a, Point b)
    60. {
    61. return (a+b)*0.5;
    62. }
    63. double area(Point a, Point b, Point c)
    64. {
    65. return fabs((b - a) ^ (c - a) * 0.5);
    66. }
    67. void solve()
    68. {
    69. Point a,b,c,p;
    70. Line ab,ac,bc;
    71. a.input();
    72. b.input();
    73. c.input();
    74. p.input();
    75. ab=Line(a,b);
    76. ac=Line(a,c);
    77. bc=Line(b,c);
    78. if(!ab.pointonseg(p)&&!ac.pointonseg(p)&&!bc.pointonseg(p))
    79. {
    80. printf("-1\n");
    81. }
    82. else
    83. {
    84. double s=area(a,b,c)/2;
    85. if(ab.pointonseg(p))
    86. {
    87. double dispa=p.distance(a);
    88. double dispb=p.distance(b);
    89. if(dispa
    90. {
    91. Point l=b,r=c;
    92. Point mid;
    93. int x=50;
    94. while(x--)
    95. {
    96. mid=mid_(l,r);
    97. int ret=sgn(area(mid,p,b)-s);
    98. if(ret>0) r=mid;
    99. else if(ret<0) l=mid;
    100. else break;
    101. }
    102. printf("%.10f %.10f\n",mid.x,mid.y);
    103. }
    104. else
    105. {
    106. Point l=a,r=c;
    107. Point mid;
    108. int x=50;
    109. while(x--)
    110. {
    111. mid=mid_(l,r);
    112. int ret=sgn(area(mid,p,a)-s);
    113. if(ret>0) r=mid;
    114. else if(ret<0) l=mid;
    115. else break;
    116. }
    117. printf("%.10f %.10f\n",mid.x,mid.y);
    118. }
    119. }
    120. else if(ac.pointonseg(p))
    121. {
    122. double dispa=p.distance(a);
    123. double dispc=p.distance(c);
    124. if(dispa
    125. {
    126. Point l=c,r=b;
    127. Point mid;
    128. int x=50;
    129. while(x--)
    130. {
    131. mid=mid_(l,r);
    132. int ret=sgn(area(p,mid,c)-s);
    133. if(ret>0) r=mid;
    134. else if(ret<0) l=mid;
    135. else break;
    136. }
    137. printf("%.10f %.10f\n",mid.x,mid.y);
    138. }
    139. else
    140. {
    141. Point l=a,r=b;
    142. Point mid;
    143. int x=50;
    144. while(x--)
    145. {
    146. mid=mid_(l,r);
    147. int ret=sgn(area(p,mid,a)-s);
    148. if(ret>0) r=mid;
    149. else if(ret<0) l=mid;
    150. else break;
    151. }
    152. printf("%.10f %.10f\n",mid.x,mid.y);
    153. }
    154. }
    155. else
    156. {
    157. double dispb=p.distance(b);
    158. double dispc=p.distance(c);
    159. if(dispb
    160. {
    161. Point l=c,r=a;
    162. Point mid;
    163. int x=50;
    164. while(x--)
    165. {
    166. mid=mid_(l,r);
    167. int ret=sgn(area(p,mid,c)-s);
    168. if(ret>0) r=mid;
    169. else if(ret<0) l=mid;
    170. else break;
    171. }
    172. printf("%.10f %.10f\n",mid.x,mid.y);
    173. }
    174. else
    175. {
    176. Point l=b,r=a;
    177. Point mid;
    178. int x=50;
    179. while(x--)
    180. {
    181. mid=mid_(l,r);
    182. int ret=sgn(area(p,mid,b)-s);
    183. if(ret>0) r=mid;
    184. else if(ret<0) l=mid;
    185. else break;
    186. }
    187. printf("%.10f %.10f\n",mid.x,mid.y);
    188. }
    189. }
    190. }
    191. }
    192. signed main()
    193. {
    194. //freopen("input.txt","r",stdin);
    195. //freopen("output.txt","w",stdout);
    196. ios;
    197. int _t=1;
    198. // cin>>_t;
    199. scanf("%d",&_t);
    200. while(_t--) solve();
    201. system("pause");
    202. return 0;
    203. }

    J

    Spy

    题意:给定n个敌人的力量值a[i],及击杀敌人获得的荣誉值p[i].给定你的第一队的力量值b[i],第二队的力量值c[i].需要将b[i]与c[j]一一配对后组成n只队伍d[],新的力量值为两人之和,d[]再与a[]随机战斗,每只队伍只能战斗一次,共n!种情况。若d[i]>a[i]我方获得荣誉值p[i].求可获得的荣誉的最大期望乘n的值,数据保证最大期望乘n后是整数

    思路:把b[]和c[]当作二分图,边的权值为这对组合可以获得的荣誉值之和。然后进行KM算法,找到最大权值匹配即为答案。

    1. #include
    2. #define ios ios::sync_with_stdio(0),cin.tie(0)
    3. #define PII pair
    4. typedef long long ll;
    5. const int N=410;
    6. const int inf=0x3f3f3f3f;
    7. const ll infll=1e15+7;
    8. using namespace std;
    9. int n;
    10. ll a[N],p[N],b[N],c[N];
    11. ll w[N][N];
    12. ll la[N], lb[N], upd[N]; // 左、右部点的顶标
    13. bool va[N], vb[N]; // 访问标记:是否在交错树中
    14. ll match[N]; // 右部点匹配了哪一个左部点
    15. ll last[N]; // 右部点在交错树中的上一个右部点,用于倒推得到交错路
    16. bool dfs(ll x, ll fa)
    17. {
    18. va[x] = 1;
    19. for(int y = 1; y <= n; y++)
    20. {
    21. if(!vb[y])
    22. {
    23. if(la[x] + lb[y] == w[x][y])
    24. {
    25. vb[y] = 1; last[y] = fa;
    26. if(!match[y] || dfs(match[y], y))
    27. {
    28. match[y] = x;
    29. return true;
    30. }
    31. }
    32. else if(upd[y] > la[x] + lb[y] - w[x][y])
    33. {
    34. upd[y] = la[x] + lb[y] - w[x][y];
    35. last[y] = fa;
    36. }
    37. }
    38. }
    39. return false;
    40. }
    41. ll KM()
    42. {
    43. for(int i = 1; i <= n; i++)
    44. {
    45. la[i] = -infll;
    46. lb[i] = 0;
    47. for(int j = 1; j <= n; j++) la[i] = max(la[i], w[i][j]);
    48. }
    49. for(int i = 1; i <= n; i++)
    50. {
    51. memset(va, 0, sizeof(va));
    52. memset(vb, 0, sizeof(vb));
    53. for(int j = 1; j <= n; j++) upd[j] = infll;
    54. // 从右部点st匹配的左部点match[st]开始dfs,一开始假设有一条0-i的匹配
    55. int st = 0; match[0] = i;
    56. while(match[st]) // 当到达一个非匹配点st时停止
    57. {
    58. ll delta = infll;
    59. if(dfs(match[st], st)) break;
    60. for(int j = 1; j <= n; j++)
    61. if(!vb[j] && delta > upd[j])
    62. {
    63. delta = upd[j];
    64. st = j; // 下一次直接从最小边开始DFS
    65. }
    66. for(int j = 1; j <= n; j++) // 修改顶标
    67. {
    68. if(va[j]) la[j] -= delta;
    69. if(vb[j]) lb[j] += delta;
    70. else upd[j] -= delta;
    71. }
    72. vb[st] = true;
    73. }
    74. while(st) // 倒推更新增广路
    75. {
    76. match[st] = match[last[st]];
    77. st = last[st];
    78. }
    79. }
    80. ll ans = 0;
    81. for(int i = 1; i <= n; i++)
    82. if(match[i])
    83. ans += w[match[i]][i];
    84. return ans;
    85. }
    86. void solve()
    87. {
    88. cin>>n;
    89. for(int i=1;i<=n;i++) cin>>a[i];
    90. for(int i=1;i<=n;i++) cin>>p[i];
    91. for(int i=1;i<=n;i++) cin>>b[i];
    92. for(int i=1;i<=n;i++) cin>>c[i];
    93. for(int i=1;i<=n;i++)
    94. for(int j=1;j<=n;j++)
    95. {
    96. ll sum=0;
    97. for(int k=1;k<=n;k++)
    98. if(b[i]+c[j]>a[k]) sum+=p[k];
    99. w[i][j]=sum;
    100. }
    101. cout<<KM()<<'\n';
    102. }
    103. signed main()
    104. {
    105. //freopen("input.txt","r",stdin);
    106. //freopen("output.txt","w",stdout);
    107. ios;
    108. int _t=1;
    109. //cin>>_t;
    110. while(_t--) solve();
    111. system("pause");
    112. return 0;
    113. }

  • 相关阅读:
    Thinkphp 5.0.24变量覆盖漏洞导致RCE分析
    【OBS】circlebuf
    耶幕上门推拿平台系统开发解析
    c 两进程(多进程)通过mmap()共享内存通信
    多点DMALL × Apache Kyuubi:构建统一SQL Proxy探索实践
    Windows任务管理器命令行查进程
    聚焦创新丨赛宁网安亮相2022未来网络发展大会成果展
    怎么合并多个PDF文件?快进来学习PDF的合并办法
    Springboot 项目下载资源目录下的 Word 文件
    多线程与线程池
  • 原文地址:https://blog.csdn.net/qq_62615329/article/details/134539480