运气不错有个抱枕。
1046 - chess play

题意:

一个n*m的数组,初始全部是’.’,然后3种操作,把一个位置变成’w’,或者把一个位置变成’r’,或者交换两行。

思路:

vector的swap是O(1)的,直接模拟就行。

//
//  main.cpp
//  chess play
//
//  Created by 翅膀 on 16/11/5.
//  Copyright © 2016年 kg20006. All rights reserved.
//#include <iostream>
#include <stdio.h>
#include <vector>
#include <algorithm>
using namespace std;
vector<int>c[1005];
int main(int argc, const char * argv[]) {int T;scanf("%d", &T);while(T--) {int n, m;scanf("%d%d", &n, &m);int q;scanf("%d", &q);for(int i = 1; i <= n; ++i) {c[i].clear();for(int j = 1; j <= m; ++j)c[i].push_back(0);}while(q--) {int t, tt, x, y;scanf("%d", &t);if(t == 1) {scanf("%d%d%d", &tt, &x, &y);if(tt == 1) c[x][y] = 1;else c[x][y] = 2;}else {scanf("%d%d", &x, &y);swap(c[x], c[y]);}}for(int i = 1; i <= n; ++i) {for(int j = 1; j <= m; ++j) {if(c[i][j] == 0) putchar('.');else if(c[i][j] == 1) putchar('w');else putchar('b');}puts("");}}return 0;
}

Best couple

题意:

n个男生,m个女生,然后给一个邻接表L[i][j],男生和女生配对的贡献是他们之间的最短路,问配对的最大贡献是多少。

思路:

先跑个floyd最短路,本来最大贡献是不一定是最大匹配的,但是因为给的邻接表是无向图,不存在这种反例,所以直接费用流就行。

//
//  main.cpp
//  Best couple
//
//  Created by 翅膀 on 16/11/5.
//  Copyright © 2016年 kg20006. All rights reserved.
//#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <queue>
using namespace std;
const int N = 505;
const int inf = ~0u>>2;
int maz[N][N];const int M = 10005;
struct eg{int u, v, cap, cost;eg(){}eg(int a, int b, int c, int d){ u = a, v = b, cap = c, cost = d; };
}edg[M<<2];
int fir[M], nex[M<<2];
int s, t, ecnt;void add(int a, int b, int c, int d){edg[ecnt] = eg(a, b, c, d);nex[ecnt] = fir[a], fir[a] = ecnt++;edg[ecnt] = eg(b, a, 0, -d);nex[ecnt] = fir[b], fir[b] = ecnt++;
}int pre[M], dis[N];
int spfa(int s, int t, int n){ //spfa求最小花费增广路queue<int>q;bool vis[N]={0};memset(pre, -1, sizeof(pre));for(int i = 0; i <= n; ++i) dis[i] = inf;dis[s] = 0; vis[s] = 1;q.push(s);while( !q.empty() ){int u = q.front(); q.pop(); vis[u] = 0;for(int k = fir[u]; k != -1; k = nex[k]){int v = edg[k].v;if( edg[k].cap && dis[u] + edg[k].cost < dis[v]){dis[v] = edg[k].cost + dis[u];pre[v] = k;if(!vis[v]){q.push(v);vis[v] = 1;}}}}return dis[t] != inf;
}
int mincostEK(int s, int t, int n){ //源点 汇点 总点数int res = 0, minflow;while( spfa(s, t, n)){minflow = inf;for(int k = pre[t]; k != -1; k = pre[edg[k].u]){minflow = min(minflow, edg[k].cap); //找到增广路上的最大可增广量}for(int k = pre[t]; k != -1; k = pre[edg[k].u]){edg[k].cap -= minflow;edg[k^1].cap += minflow;}res += dis[t] * minflow; //根据题目修改}return res;
}int main(int argc, const char * argv[]) {int T;scanf("%d", &T);while(T--) {memset(fir, -1, sizeof(fir)); ecnt = 0;int n, m;scanf("%d%d", &n, &m);for(int i = 1; i <= n+m; ++i) {for(int j = 1 ; j <= n+m; ++j) {scanf("%d", &maz[i][j]);if(maz[i][j] == -1) maz[i][j] = inf;}}s = 0, t = n+m+1;for(int k = 1; k <= n+m; ++k) {for(int i = 1; i <= n+m; ++i) {for(int j = 1; j <= n+m; ++j) {maz[i][j] = min(maz[i][j], maz[i][k]+maz[k][j]);}}}for(int i = 1; i <= n+m; ++i) {for(int j = 1; j <= n+m; ++j) {printf("%d ", maz[i][j]);}puts("");}for(int i = 1; i <= n; ++i) {add(s, i, 1, 0);for(int j = n+1; j <= n+m; ++j) {if(maz[i][j] == inf) continue;add(i, j, 1, -maz[i][j]);}}for(int j = n+1; j <= n+m; ++j) {add(j, t, 1, 0);}int ans = -mincostEK(s, t, t+5);printf("%d\n", ans);}return 0;
}

1048 - Best substring

题意:

给一个字符串,然后val[i]表示以i为中心的最长回文子串的长度,然后求一个子串,满足∑leni=1(−1)k+1∗i∗val[k]\sum_{i=1}^{len}(-1)^{k+1}*i*val[k]最大,其中k是i在原串中的位置。
简单的说就是给一个数组,然后去掉一个前缀和后缀(可能为空),要求∑leni=1i∗a[i]\sum_{i=1}^{len}i*a[i]最大。

思路:

先跑马拉车求出val数组,然后推一下发现可以斜率优化,就是这个题。

//
//  main.cpp
//  Best substring
//
//  Created by 翅膀 on 16/11/5.
//  Copyright © 2016年 kg20006. All rights reserved.
//#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
typedef long long ll;
const int N = 2e5+5;
char str[N];
char s[N*2];
int sl[N*2]; //p[i]表示以i为中轴的最长回文长度
void manacher(char *str, int len){memset(sl, 0, sizeof(sl));int id = 0;for(int i = len; i >= 0; --i){s[2*i+2] = str[i];s[2*i+1] = '#';}s[0] = '$', s[2*len+2] = '\0';int up = 2*len+1;for(int i = 2; i < up; ++i){if(sl[id] + id > i) sl[i] = min(sl[2*id-i], sl[id]+id-i);else sl[i] = 1;while(s[i-sl[i]] == s[i+sl[i]]) ++sl[i];if(id+sl[id] < i+sl[i]) id = i;}
}
ll val[N], sum[N], p[N];
int q[N], tail, top;
inline ll y(int x){ return p[x] - x*sum[x]; }
double g(int j, int k){double dy = y(j) - y(k);double dx = j - k;return dy/dx;
}
inline ll getans(int i, int j){return p[i] - p[j] - j*(sum[i] - sum[j]);
}
int solve(ll x){int l = top, r = tail-1, mid, res = l;while(l <= r){mid = (l+r) >> 1;if(g(q[mid], q[mid-1]) < -x) l = mid+1, res = mid;else r = mid-1;}return q[res];
}
int main(int argc, const char * argv[]) {int T;scanf("%d", &T);while(T--) {int n;scanf("%d %s", &n, str);manacher(str, n);for(int i = 1; i <= n; ++i) {val[i] = sl[i*2]-1;if(i%2 == 0) val[i] *= -1;}for(int i = 1; i <= n; ++i) {sum[i] = sum[i-1]+val[i];p[i] = p[i-1] + i*val[i];}top = tail = 0;q[tail++] = 0;ll ans = 0;for(int i = 1; i <= n; ++i){int j = solve(sum[i]);ans = max(ans, getans(i,j));while(top < tail-1 && g(i, q[tail-1]) < g(q[tail-1], q[tail-2])) tail--;q[tail++] = i;}printf("%lld\n", ans);}return 0;
}

1049 - Deg-route

题意:

求从(0,0)走到(x,y),其中x>=y,且不穿过y=x的方案数。

思路:

考虑从(0,0)走到(x,y)且穿过y=x的方案数,设为l(x,y)。
那么考虑第一次穿过的位置,设为(q,q)。
当遍历q从0到y-1时,方案数是不重不漏的,因为每种方案必然有第一次穿过的位置,且位置唯一。
设Cat(i)表示第i个卡特兰数,我们知道卡特兰数是(0,0)走到(i,i)不经过y=x的路径数,那么就可以表示出l(x,y)了。

l(x,y)=∑i=0y−1Cat(i)∗Cx−ix−i+y−i−1

l(x,y)=\sum_{i=0}^{y-1}Cat(i)*C_{x-i+y-i-1}^{x-i}
这个式子的意思是枚举第一次穿过的点(i,i)然后走到这个点的方案数乘上这个点往上走了一步之后,再任意走到(x,y)的方案数。
这个式子的解:

l(x,y)=Cx+1x+1+y−1

l(x,y)=C_{x+1+y-1}^{x+1}
也就是说等价于从(-1,1)走到(x,y)的方案数,我们来从组合学分析一下就知道,这是个十分优美的结论。

首先条件是只能往x和y的正半轴走,并且要求穿过y=x。
穿过y=x并不是直观的条件,考虑到穿过的那一步必须是往上走的,那么穿过y=x就等价于与y=x+1相交或者相接触,此时根据x>=y,(x,y)是与y=x+1相离的。
注意到(-1,1)与(0,0)关于y=x+1对称,那么从(-1,1)走到(x,y),是必然接触y=x+1的,因为(-1,1)与(x,y)分别处于y=x+1分割的两个半平面内,假设一条路径与y=x+1的交点是(p,p+1),在相交之前走的路径,我们总可以找到一条从(0,0)到(p,p+1)的路径与之对应,根据对称性:
当(-1,1)出发的路径往上走,那么(0,0)出发的路径就往右走。
当(-1,1)出发的路径往右走,那么(0,0)出发的路径就往上走。
当(0,0)走到了(p,p+1),之后的路就按照(-1,1)的走法走就行了。
容易证明这是不重不漏,一一对应的,这样我们就给出了一个组合学的解释,从(0,0)走到(x,y)穿过y=x的方案数等价于从(-1,1)走到(x,y)的方案数。

那么最后答案就是总的减去不合法的:

ans=Cxx+y−Cx+1x+1+y−1

ans=C_{x+y}^{x}-C_{x+1+y-1}^{x+1}
因为模数较小,lucas即可。

//
//  main.cpp
//  Deg-route
//
//  Created by 翅膀 on 16/11/5.
//  Copyright © 2016年 kg20006. All rights reserved.
//#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
typedef long long ll;
const int MX = 1e5;
const ll mod = 1e4+7;
ll fac[MX];
ll pow_mod(ll a, ll k) {ll res = 1;while(k) {if(k&1) res = (res*a)%mod;a = (a*a)%mod;k >>= 1;}return res;
}
ll C(ll n, ll k){if(n < k || n < 0 || k < 0) return 0;return fac[n]*pow_mod(fac[n-k]*fac[k]%mod, mod-2)%mod;
}
ll lucas(ll a, ll b){if(b == 0) return 1;return lucas(a/mod, b/mod) * C(a%mod, b%mod) % mod;
}
void init(){ //初始化阶乘fac[0] = fac[1] = 1;for(int i = 2; i <= mod; ++i) fac[i] = fac[i-1]*i%mod;
}int main(int argc, const char * argv[]) {init();int T;scanf("%d", &T);while(T--) {int x, y;scanf("%d %d", &x, &y);printf("%lld\n", (lucas(x+y, x)-lucas(x+y, x+1)+mod)%mod);}return 0;
}

1050 - array

题意:

给一个数组a,问有多少个子序列满足第一个数是1,后一个是前一个的两倍。

思路:

直接dp,dp[i]表示以i结尾的子序列个数,另外用个pre[i]表示2^i的个数。

//
//  main.cpp
//  array
//
//  Created by 翅膀 on 16/11/5.
//  Copyright © 2016年 kg20006. All rights reserved.
//#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <string.h>
#include <map>
using namespace std;
typedef long long ll;
const int N = 1e5+5;
const ll mod = 1e9+7;
ll a[N];
ll dp[N], pre[35];
int aa[N];
map<ll, int>cnt;
int check(ll x) {if((x&(x-1)) != 0) return -1;return cnt[x];
}
int main(int argc, const char * argv[]) {cnt[1] = 0;for(int x = 1, i = 2; i <= 1000000000; i <<= 1, ++x) {cnt[i] = x;}int T;scanf("%d", &T);while(T--) {memset(dp, 0, sizeof(dp));memset(pre, 0, sizeof(pre));int n;scanf("%d", &n);for(int i = 1; i <= n; ++i) {scanf("%lld", a+i);aa[i] = check(a[i]);}ll ans = 0;for(int i = 1; i <= n; ++i) {int tmp = aa[i];if(tmp == 0) dp[i] = 1;else dp[i] = pre[tmp-1];pre[tmp] = (pre[tmp]+dp[i])%mod;ans = (ans+dp[i])%mod;}printf("%lld\n", ans);}return 0;
}

1051 - My-graph

题意:

问n个点的图能不能构造出原图和补图同构的图。

思路:

满图有n*(n-1)/2条边,至少边数要是偶数,猜了一发过了,实际上这是个充要条件。

//
//  main.cpp
//  My-graph
//
//  Created by 翅膀 on 16/11/5.
//  Copyright © 2016年 kg20006. All rights reserved.
//#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <string.h>
using namespace std;
int main(int argc, const char * argv[]) {int T;scanf("%d", &T);while(T--) {int n;scanf("%d", &n);if((n*(n-1)/2)%2 == 1) puts("no");else puts("yes");}return 0;
}

1052 - See car

题意:

一个人站在(a,b),然后他的右下方有一些点,问你能看到的点的数量。

思路:

存下斜率就行。

//
//  main.cpp
//  See car
//
//  Created by 翅膀 on 16/11/5.
//  Copyright © 2016年 kg20006. All rights reserved.
//#include <iostream>
#include <algorithm>
#include <stdio.h>
#include <set>
using namespace std;
typedef long long ll;
ll gcd(ll a, ll b) { return b? gcd(b, a%b) : a; }
struct dom{ll up, down;void loli() {ll tmp = gcd(up, down);up /= tmp, down /= tmp;}dom(ll a, ll b) { up = a, down = b; loli(); }bool operator < (const dom& z) const {return up*z.down < z.up*down;}
};
set<dom>st;
int main(int argc, const char * argv[]) {int T;scanf("%d", &T);while(T--) {ll a, b, n;scanf("%lld%lld%lld", &a, &b, &n);st.clear();for(ll x, y, i = 1; i <= n; ++i) {scanf("%lld %lld", &x, &y);st.insert(dom(y-b, x-a));}printf("%lld\n", (ll)st.size());}return 0;
}

1053 - Gemstone digger

题意:

n个宝藏,去第i个地方有a[i]个宝藏,在i采宝藏的死的概率是pi,每个地方相互独立,问存活率>0.19的情况下最多采多少个宝藏。

思路:

dp[i][j]表示前i个宝藏中一共采了j个时最大的存活率是多少。
dp[i][j] = dp[i-1][j];
if(j >= a[i]) dp[i][j] = max(dp[i][j], dp[i-1][j-a[i]]*(1-pi))
跑完后扫一遍找存活率大于0.19的最多宝藏。

//
//  main.cpp
//  Gemstone digger
//
//  Created by 翅膀 on 16/11/5.
//  Copyright © 2016年 kg20006. All rights reserved.
//#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
int a[1005];
double p[1005];
double dp[105][50005];
int main(int argc, const char * argv[]) {int T;scanf("%d", &T);while(T--) {int n;int tot = 0;scanf("%d", &n);for(int i = 1; i <= n; ++i) {scanf("%d", a+i);tot += a[i];}for(int i = 1; i <= n; ++i) {scanf("%lf", p+i);}memset(dp, 0, sizeof(dp));dp[0][0] = 1;for(int i = 1; i <= n; ++i) {for(int j = 0; j <= tot; ++j) {if(j >= a[i]) dp[i][j] = max(dp[i-1][j], dp[i-1][j-a[i]]*(1-p[i]));else dp[i][j] = dp[i-1][j];}}int ans = 0;for(int i = 1; i <= n; ++i) {for(int j = 0; j <= tot; ++j) {if(dp[i][j] > 0.19) ans = max(ans, j);}}printf("%d\n", ans);}return 0;
}

1054 - String cut

题意:

给一个字符串,可以删一个字符,删完后要求串是由一个子串重复k次构成的,求最大的k。

思路:

字符串不会做,待队友补。

1055 - Ball-box

题意:

一个盒子一开始有n个球,每个球标号唯一,先执行操作1,如果两个球x,y满足|x-y|不在盒子里,那么久把|x-y|放进去,设操作次数为p1,然后执行操作2,不断摸球,直到所有球都被摸过,设操作次数为p2,求p1+p2的期望。

思路:

如果两个球x,y在盒子里,设x>=y,那么gcd(x,y) == gcd(x,x-y),可以推出最后所有数的gcd等价于一开始所有数的gcd,那么操作1的次数就是最大的数/gcd。
操作2的次数容易推导,设dp[i]表示已经摸了i个球,直到摸完所有球的期望次数。显然有dp[n]=0,dp[i]=i/n∗dp[i]+(n−i)/n∗dp[i+1]+1dp[n]=0,dp[i] = i/n*dp[i] + (n-i)/n*dp[i+1]+1
化简下dp[n] = 0, dp[i] = dp[i+1]+n/i。
那么dp[0] = n*Hn,其中Hn是调和级数。
然后算就行了。
注意需要特判0。

//
//  main.cpp
//  Ball-box
//
//  Created by 翅膀 on 16/11/5.
//  Copyright © 2016年 kg20006. All rights reserved.
//#include <iostream>
#include <stdio.h>
#include <string.h>
using namespace std;
const int N = 60005;
int gcd(int a, int b) { return b? gcd(b, a%b) : a; }
int a[N];
int main(int argc, const char * argv[]) {int T;scanf("%d", &T);while(T--) {int n, mx = -1, zr = 0;scanf("%d", &n);for(int i = 1; i <= n; ++i) {scanf("%d", a+i); mx = max(mx, a[i]);if(a[i] == 0) zr = 1;}int tmp = a[1];for(int i = 2; i <= n; ++i) {tmp = gcd(tmp, a[i]);}int tot = mx/tmp+zr;double ans = 0;for(int i = 1; i <= tot; ++i) {ans += 1.0*tot/i;}ans += (tot-n);printf("%d\n", (int)ans);}return 0;
}

“玲珑杯”ACM比赛 Round #4相关推荐

  1. 玲珑杯”ACM比赛 Round #8-D XJT Loves Boggle(dfs)

    记录一个菜逼的成长.. DESCRIPTION Boggle is a word game designed by Allan Turoff and distributed by Hasbro. It ...

  2. “玲珑杯”ACM比赛 Round #21-C-战舰萝莉(线段树区间更新)

    "玲珑杯"ACM比赛 Round #21 Start Time:2017-09-23 17:00:00 End Time:2017-09-23 19:30:00 Refresh T ...

  3. “玲珑杯”ACM比赛 Round #18 C -- 图论你先敲完模板【Dp】

    C -- 图论你先敲完模板 Time Limit:5s Memory Limit:256MByte Submissions:660Solved:160 DESCRIPTION 今天HHHH在操场上跑步 ...

  4. “玲珑杯”ACM比赛 Round #18 ABC题解

    A -- 计算几何你瞎暴力 Time Limit:5s Memory Limit:256MByte Submissions:1597Solved:301 DESCRIPTION 今天HHHH考完了期末 ...

  5. 玲珑杯”ACM比赛 Round #15 D 咸鱼商店【二分+01背包】

    题目链接:http://www.ifrog.cc/acm/problem/1125 题目大意:中文题目,题意请仔细看题面. 解题思路:二分+01背包     01背包的最终结果与其中的顺序无关,我们要 ...

  6. lonlifeOJ1152 “玲珑杯”ACM比赛 Round #19 概率DP

    E -- Expected value of the expression DESCRIPTION You are given an expression: A0O1A1O2A2⋯OnAnA0O1A1 ...

  7. “玲珑杯”ACM比赛 Round #22 E【贪心】

    题目: http://www.ifrog.cc/acm/problem/1171?contest=1024&no=4 题意: 输入一个字符串,将他重新排列,使得重排之后的字符串的最小表示法,最 ...

  8. “玲珑杯”ACM比赛 Round #24: C. この戦いが終わったら(BFS+bitset优化暴力)

    C -- この戦いが終わったら 给你一个无向图,每次查询的时候给一堆二元组(xi,yi) 求图中有多少个点u与至少一个这次询问给出的二元组(xi,yi)满足dist(u,xi)<=yi,dist ...

  9. “玲珑杯”ACM比赛 Round #19

    A -- A simple math problem Time Limit:2s Memory Limit:128MByte Submissions:1599Solved:270 DESCRIPTIO ...

最新文章

  1. CTF(pwn)堆利用 之 off by one
  2. Html颜色值 to RGB
  3. Vmware由于centos升级内核不可运行(C header files matching your running kernel were not found)的解决方案...
  4. 如何获取url中的参数并传递给iframe中的报表
  5. 洛阳地铁一号线无人驾驶_刚刚,最新消息!涉及洛阳地铁1号线、2号线…
  6. 迁移到云端之前需要考虑哪些问题?
  7. fanuc系统md和mf区别_fanuc mf系统小技巧汇总
  8. 30天自制操作系统——Day8实验报告
  9. 2010年6月16日最新NOD32激活码和升级ID(含ESS/EAV)
  10. u深度重装系统详细教程_U盘怎样使用U深度给电脑装系统教程
  11. 还原 对于 服务器“DESKTOP-BNNIISU\SQLEXPRESS”失败。  (Microsoft.SqlServer.SmoExtended)
  12. (待补充)【读书笔记】20190809《运营之光》——黄有璨
  13. idea run with coverage异常
  14. 零基础学python_03_字符串(拼接+换行+制表符)
  15. 用python六行代码写一个简单的键盘记录器
  16. python 做表格分析_Python 处理分析 128 张 Excel 表格竟不到3秒?| 附数据集
  17. Tableau培训学习笔记3:空间数据分析——科比投篮以及新冠肺炎分析(带数据)
  18. uni-icons 图标
  19. 图像预处理(二值化)
  20. Java判断字符串是中文还是英文

热门文章

  1. 802.11n关键技术
  2. 国外企业电子邮箱大全,国外用邮箱哪个好?怎么注册国外邮箱?
  3. 中职 计算机专业,中职计算机专业发展新思维
  4. MySQL之初识MySQL
  5. 安全信息管理系统(OSSIM)
  6. C++活到老学到老 auto
  7. 苹果市场占有率_为什么买了苹果电脑,却要安装Windows系统
  8. 知意字稿的语音转文字功能真的好用吗?
  9. 令人惊叹的、不起眼的硅片
  10. Environment.SpecialFolder的值的含义(本地打印)