Codeforces pupil
图一乐图一乐
这个作者很懒,什么都没留下…
展开
-
CF123E Maze(数学期望,dfs求子树和)
题意:给你一个n-1个结点的树,给出每个点作为入口和出口的概率。求从入口走到出口的期望步数。分析:当考虑一个点为入口,其他点如果在出口之前被dfs过,则出现2次,否则出现1次,当出口确定,一个点在之前被访问的概率是1/2(类似于插空,可以往前插,可以往后插)。现在考虑一个点为出口(它的概率是chu[u]),先dfs出子树中结点的个数和以子树中结点为入口的概率,这个子树对期望的贡献就是sz[i]∗sumpro[i]∗chu[u]sz[i]*sumpro[i]*chu[u]sz[i]∗sumpro[i]∗ch原创 2020-11-03 21:06:50 · 241 阅读 · 0 评论 -
E. Deleting Numbers(分类讨论,交互题)
int p[N], cnt;bool vis[N + 1];void x_x(){ f(i, 2, N) { if (!vis[i])p[++cnt] = i; for (int j = 1;p[j] <= N / i;j++) { vis[p[j] * i] = true; if (i%p[j] == 0)break; } }}int query2(char c, int x){ printf("%c %d", c, x); cout <<原创 2020-09-20 22:41:25 · 97 阅读 · 0 评论 -
E. Expected Damage(概率)
const int N = 2e5+5, M = 26;ll p[N];int d[N];int main(){ //freopen("in.txt", "r", stdin); int n, m; while (cin >> n >> m) { f(i, 1, n)d[i] = in(); sort(d + 1, d + 1 + n); f(i, 1, n)p[i] = p[i - 1] + d[i]; f(i, 1, m) { int a原创 2020-09-20 22:35:43 · 194 阅读 · 0 评论 -
D - Discrete Centrifugal Jumps(单调栈dp)
const int N = 6e5 + 5, M = 22;int a[N], f[N];int main(){ //freopen("in.txt", "r", stdin); int n; while (cin >> n) { f(i, 1, n)a[i] = in(); deque<int> pos, neg; pos.push_back(1); neg.push_back(1); f(i, 2, n) { f[i] = inf;原创 2020-09-09 12:19:49 · 182 阅读 · 0 评论 -
A - Apple Trees(经典矩阵快速幂解决递推问题)
思路:考虑转移方程f(n,0)=f(n−1,9)∗16+f(n−1,19)∗9+f(n−1,29)∗4+f(n−1,39)∗1f(n,0)=f(n-1,9)*16+f(n-1,19)*9+f(n-1,29)*4+f(n-1,39)*1f(n,0)=f(n−1,9)∗16+f(n−1,19)∗9+f(n−1,29)∗4+f(n−1,39)∗1,这是对于年龄为0岁的树而言,对于其他的<=44的树,其转移方程为f(n,i)=f(n−1,i−1)f(n,i)=f(n-1,i-1)f(n,i)=f(n−1,i−原创 2020-08-25 11:11:44 · 178 阅读 · 0 评论 -
F. Crossword Expert(组合数学,前缀期望)
题意:给n个问题,给出每个问题的解决时间ti,对于每个问题需要ti或ti+1个单位时间去解决,且要按给出的顺序解决,求在T时间内,对于解决问题个数的期望。思路:先假设每个问题时间消耗都是ti+1t_i+1ti+1,求出f[i]f[i]f[i](解决问题个数大于等于i的概率),然后利用f[i]−f[i−1]f[i]-f[i-1]f[i]−f[i−1]求出解决问题个数等于i的个数,并求其贡献。至于求f[i]f[i]f[i],可以这样考虑,对于前序i−1i-1i−1个问题,全部取ti+1t_i+1ti+1原创 2020-08-21 22:34:30 · 264 阅读 · 0 评论 -
D. Makoto and a Blackboard(dp,积性函数)
思路:考虑n的所有质因子,求其期望,再乘起来。考虑dp数组,第一维表示当前是第几步,第二维表示当前因子的次数,然后每次对每种次数进行更新,次数高的可以向低的等概率转移。const int N = 1e4+5;ll n, k;ll INV[65];ll f[N][65];ll cal(ll num, int cishu){ f(i, 0, cishu - 1)f[0][i] = 0; f[0][cishu] = 1; f(i,1,k) f(j, 0, cishu) { f[i][原创 2020-08-20 19:31:56 · 153 阅读 · 0 评论 -
E - Decypher the String(交互题)
思路:利用分块的思想,逐步定位。/*痛みを受け取れ,痛みを知れ*/#include<bits/stdc++.h>#define f(i,a,b) for(register int i=a;i<=b;++i)#define ff(i,a,b) for(register int i=a;i>=b;--i)#define debug(x) cerr << #x << " : " << x << " " << endlu原创 2020-08-14 09:22:37 · 92 阅读 · 0 评论 -
D - Magic Gems(dp+矩阵快速幂)
/*痛みを受け取れ,痛みを知れ*/#include<bits/stdc++.h>#define f(i,a,b) for(register int i=a;i<=b;++i)#define ff(i,a,b) for(register int i=a;i>=b;--i)#define debug(x) cerr << #x << " : " << x << " " << endlusing namespace st原创 2020-08-14 09:20:29 · 135 阅读 · 0 评论 -
F. Guess Divisors Count(数论构造)
ll ju = 1e9,ju2=1e18;int p[1050], cnt;bool vis[1050];vector<ll> v,v2;const ll mp[22] = { 53,89,131,167,199,//每次询问最大的质数的后面一个 241,281,331,373,409, 443,479,521,569,601, 641 };void x_x(){ f(i, 2, 1000) { if (!vis[i])p[++cnt] = i;原创 2020-08-04 20:50:59 · 158 阅读 · 0 评论 -
Number Challenge CodeForces - 235E(莫比乌斯反演,约数函数性质)
学习地址总结:莫比乌斯反演的题目是很有套路的,要学会从枚举约数到枚举倍数的改变,另外这里的约数函数的等价式需要记下。const int N = 2e3+5;ll mo = 1ll<< 30;int p[N + 1], mob[N + 1], cnt,d[N][N];bool vis[N + 1];void x_x(){ mob[1] = 1; f(i, 2, N) { if (!vis[i]) { p[++cnt] = i; mob[i] = -1;原创 2020-08-04 12:11:36 · 140 阅读 · 0 评论 -
D. White Lines(思维)
题意:给个N*N的黑白矩阵,给大小k的橡皮,求擦一次最多能有多少行列全部都是白色的。思路:对每一行,每一列求其贡献,如果其中没有黑色格子,说明这个行或者列对任意格点为左上角的操作都有贡献,如果最后一个黑子和第一个黑子的距离超过k,则是无法覆盖的,否则,这个行或列对一下符合条件的格点具有贡献。const int N = 2005;int p[N][N];//以每一个点为左上角的贡献char s[N][N];int main(){ //STDIN; int n, k; cin >>原创 2020-07-24 20:32:14 · 144 阅读 · 0 评论 -
C - Choosing flowers(思维)
思路:可以由反证法想到,对于第二属性,必定是选择一种,然后贪心替换第一属性中比当前第二属性大的。int a[N],b[N],c[N];ll p[N];int main(){ //freopen("in.txt", "r", stdin); int t; int n,m; cin >> t; while (t--) { scanf("%d%d", &n, &m); f(i, 1, m) { scanf("%d%d", &a[i], &a原创 2020-07-21 10:47:39 · 246 阅读 · 0 评论 -
C2 - Skyscrapers (hard version)(单调栈)
思路:从左到右求一遍单调栈,,每次维护前缀,再倒着来一次。int a[N];ll p[N], fp[N];int main(){ //freopen("in.txt", "r", stdin); int n; while (cin >> n) { f(i, 1, n)scanf("%d", &a[i]); stack<int> st; f(i, 1, n)//从左到右求一遍单调栈,递增 { while (!st.empty() &原创 2020-07-19 12:19:33 · 190 阅读 · 0 评论 -
D - Petya and Array(树状数组,二分)
思路:对于al+..ara_l+..a_ral+..ar这种区间和问题一般都要考虑前缀差,然后问题就转化为了求sum[r]−sum[l−1]<tsum[r]-sum[l-1]<tsum[r]−sum[l−1]<t,对等式移项sum[r]−t<sum[l]sum[r]-t<sum[l]sum[r]−t<sum[l],然后又发现是要查询有几个前缀大于当前的前缀减去t,所以用树状数组把前序的前缀存起来,这里数据是1e9,所以判断大小不能直接比大小,用到排序,比较相对大小。还原创 2020-07-17 09:57:50 · 243 阅读 · 0 评论 -
B. DZY Loves Modification(优先队列加枚举)
思路:贪贪贪!ll r[N], c[N];multiset<ll> str, stc;int main(){ //freopen("in.txt", "r", stdin); int n, m, k, p,x; while (cin >> n >> m >> k >> p) { f(i, 1, n) { f(j, 1, m)//记录每行每列的和 { scanf("%d", &x); r[i原创 2020-07-15 22:02:59 · 128 阅读 · 0 评论 -
C. Painting Fence(递归)
int a[N];pii find(int l, int r){ pii ans = { 2e9,0 }; f(i, l, r) { ans.first = min(ans.first, a[i]); ans.second = max(ans.second, a[i]); } return ans;}int get(int l, int r){ pii val = find(l, r); if (val.first == 0)return 0; if (val.first == val原创 2020-07-15 21:07:29 · 377 阅读 · 0 评论 -
E. Compress Words(前后缀hash)
#include<bits/stdc++.h>#define f(i,a,b) for(register int i=a;i<=b;++i)#define ff(i,a,b) for(register int i=a;i>=b;--i)#define debug(x) cerr << #x << " : " << x << " " << endlusing namespace std;typedef long lo原创 2020-07-14 10:53:50 · 279 阅读 · 0 评论 -
D - Police Stations(bfs)
题意:n个城市,k个警察局,求最多删除几条边,使得每个城市都可以在d长度内到达一个警察局。思路:贪心,使得每个城市的居民去离他最近的警察局,那么就可以有一些不必要的边可以被删除。然后用map存储下每条边的标号。从所有警察局开始深度搜索,遇到没有被接受的,并且本身没有警察局的城市就接受他,说明当前这条道路是该城市到警察局的最短路。unordered_set<int> st;queue<int> q;vector<int> G[N];map<pii, int&原创 2020-07-11 15:41:53 · 138 阅读 · 0 评论 -
E. Counting Arrays(筛法+组合数学)
题意:把一个数x,分成长度为y的数组的乘积,求有几种方案思路:题目的本质就是将x的质因子进行划分,求有几种组合方案。可以这么想,对于他的每一种质因子分配到y组,且允许为空,其实就是允许有空的隔板法,假如当前数对于质因子5,它的次数是4次,分到长度为y的数组,那么组合数是C(5−1+y,y−1)C(5-1+y,y-1)C(5−1+y,y−1)关于隔板法。最后考虑符号的问题,发现只能取偶数个符号也就是C(y,0)+C(y,2).....C(y,0)+C(y,2).....C(y,0)+C(y,2).....,原创 2020-07-10 20:16:53 · 347 阅读 · 0 评论 -
D. String Mark(思维+组合数学)
题意:求利用a的字符集,构造字典序大于a,而小于b的字符串c的种数。思路:前缀的思想,求出利用a的字符集能构造出几个小于b的字符串,减去用a的字符集构造出小于a的字符串个数。而对于其中的计算,主要考验一些思维,这种题最好能多出几个具有代表性的样例。ll fact[N+1], infact[N+1],Inv[N+1],n;char a[N], b[N];int mp[27];void x_x(){ fact[0] = infact[0] = 1; f(i, 1, N) { fact[i]原创 2020-07-10 17:39:08 · 217 阅读 · 0 评论 -
B. Buildings(手镯问题)
思路:先求出不同种类墙的数量,然后就是一个裸的手镯问题。手镯问题如下:int main(){ //freopen("in.txt", "r", stdin); ll m, n, c; while (cin >> n >> m >> c) { ll num = quickmod(c, n*n, mod); ll ans = 0; f(i, 1, m) { ll d = gcd(i,m); ans += quickmod(num, d原创 2020-07-09 14:40:10 · 131 阅读 · 0 评论 -
J. Even Numbers(组合数学找规律)
公式:n+1−pow(2,n的二进制中1的个数)n+1-pow(2,n的二进制中1的个数)n+1−pow(2,n的二进制中1的个数)ll fact[100], infact[100];void x_x(){ fact[0] = infact[0] = 1; f(i, 1, 100) { fact[i] = fact[i - 1] * i%mod; infact[i] = infact[i - 1] * inv(i, mod) % mod; }}ll C(ll a, ll b){原创 2020-07-09 10:01:06 · 175 阅读 · 0 评论 -
C. Shaass and Lights(组合数学)
const int N = 1e3 + 5;ll fact[N+1], infact[N+1];void x_x(){ infact[0] = fact[0] = 1; f(i, 1, N-1) { fact[i] = fact[i - 1] * i%mod; infact[i] = infact[i - 1] * inv(i, mod)%mod; }}ll C(int a, int b){ return fact[a] * infact[a - b] % mod*infact原创 2020-07-08 19:42:41 · 172 阅读 · 0 评论 -
D. Vasya and Triangle(构造)
int main() //构造{ //freopen("in.txt", "r", stdin); ll m, n, k; while (cin >> n >> m >> k) { if (2 * n*m%k != 0) { puts("NO");continue; } ll d = gcd(2 * m, k); puts("YES"); cout << "0 0" << endl; if (d == 1)//n%k=原创 2020-07-07 16:03:12 · 178 阅读 · 0 评论 -
C - Phone Numbers(思维)
思路:对于n<k,必定是s+(k-n)个min字符,对于n>=k,贪心取,更改最后一个不为max字符的字符,将它改成大于最小的字符,并把后的字符全部输出min字符。int main() { //freopen("in.txt", "r", stdin); int n, k; while (cin >> n >> k) { string s; cin >> s; map<char, int> mp; for (auto I原创 2020-07-06 21:44:20 · 156 阅读 · 0 评论 -
E2. Asterism (Hard Version)(思维)
const int N = 6e5 + 5;int t;int main(){ ios::sync_with_stdio(false);cin.tie(nullptr); //freopen("in.txt", "r", stdin); int n, p; while (cin >> n >> p) { vector<int> a(N); f(i, 1, n)cin >> a[i]; sort(a.begin()+1, a.begin原创 2020-07-03 10:23:43 · 363 阅读 · 0 评论 -
D. Maximum Sum on Even Positions(思维,最大连续子段和)
思路:分类讨论:1.对于交换长度为奇数的子串,偶数位上的和是不会变的。2.对于交换长度为偶数的子串,奇偶位上的和会互换。对于第二种情况,继续思考,会发现这是一个最大连续字段和的问题,对于前序贡献为负的情况,抛弃前序。然后所给的数组长度可能为奇数,所以ll a[N];int main(){ cin >> t; while (t--) { int n; scanf("%d", &n); ll now = 0; f(i, 1, n) { scanf原创 2020-06-26 12:32:52 · 307 阅读 · 0 评论 -
C. Ehab and Prefix MEXs(模拟)
思路:首先判断是否有解,如果当前的a[i]>i,表示前面(i-1)个位置有i个数填好了,矛盾。之后,求解,先用集合将可能的选择存起来,如n=4,st=[0,1,2,3,4],然后扫一遍a[],把后序要出现的数预留好,也就是剔除一些当前位置不可以出现的数,stt=[0,0,0,2],st[1,3,4],当stt只剩下[2],表示0自由了,可以使用,加入到st。int a[N];int main() { //freopen("in.txt", "r", stdin); int n; scanf原创 2020-06-20 22:56:47 · 516 阅读 · 0 评论 -
D. Yet Another Monster Killing Problem(贪心)
思路:贪心,预处理出每个天数下的最大能力值,然后贪心搜一遍。int t;int a[N];int p[N], pp[N];int main(){ //freopen("in.txt", "r", stdin); int n, m; cin >> t; while (t--) { scanf("%d", &n); int mx = 0; f(i, 1, n)scanf("%d", &a[i]), mx = max(mx, a[i]); scanf原创 2020-06-11 13:52:20 · 167 阅读 · 0 评论 -
C. Multiplicity(dp)
优化过程:f[i][j]f[i][j]f[i][j]表示从前i个中选子串长度为j的方案数,对当前集合进行划分得到状态表示:f[i][j]=f[i−1][j−1]+f[i−1][j]f[i][j]=f[i-1][j-1]+f[i-1][j]f[i][j]=f[i−1][j−1]+f[i−1][j],发现用到的都是上一层的状态,所以改成滚动数组版本,内层从大到小,保证用的状态是上一层的,同时发现时间复杂度很高,考虑预处理出每一层可用来迭代的约数。int f[N];vector<vector<in原创 2020-06-09 15:28:52 · 173 阅读 · 0 评论 -
D2. Optimal Subsequences (Hard Version)(贪心,树状数组,二分)
题意:给个序列n,给m次操作,每次操作输入k,pos,求原序列长度为k的子序列(子序列满足是所有长度为k的子序列中和最大的,和相同的情况下,取字典序小的)中第pos个元素的值。思路:选k个元素,要求和最大,肯定是从大的元素开始选,而对于元素大小相同的元素,取坐标小的,这样字典序是小的。然后将m次操作,按k从小到大进行排序,这样可以维护一个有关元素坐标的树状数组,对于求第pos个元素,可以利用树状数组+二分求第pos个元素的下标。int n, m;int tree[N];void add(int k,原创 2020-06-07 11:56:31 · 345 阅读 · 0 评论 -
D2. RGB Substring (hard version)(前缀)
题意:给个字符串,求最小修改几个字符,使得其中出现一段长度为k的子串是"RGBRGBRGBRGB…"的子串,对于每个长度为k的子串,它有三种可能的顺序,开3个前缀数组记录每个位置对于三种顺序需要改多少个,然后枚举维护每一段长度为k的子串关于每个顺序的最小值。int t;int p[3][N];int main(){ string s; int n, k; cin >> t; string ju = "RGB"; while (t--) { scanf("%d%d", &原创 2020-06-07 10:10:20 · 201 阅读 · 0 评论 -
D. Distinct Characters Queries(二分or树状数组)
题意:给个字符串,给两种操作,操作1:将字符串的第pos个字符值改成c,操作2:求[l,r]中的不同的字符数量。1.自己的思路开26个数组记录每个字符出现的位置,对于操作1,二分找到要在原字符的数组中删除的位置,二分找到在新字符的数组中插入的位置。对于操作2,对于26个字符分别二分,求出是否存在[l,r]之间的。然后效率比较慢,2000ms的题目勉强1800ms过了。**vector<vector<int> > v(26);int main(){ string s; c原创 2020-06-06 23:16:41 · 187 阅读 · 0 评论 -
E2 - Three Blocks Palindrome (hard version)(前缀,枚举)
int main(){ cin >> t; while (t--) { int n,x;cin >> n; vector<vector<int> > pre(n+1, vector<int>(201));//每个位置中每个数的前缀个数 vector<vector<int> >v(201); f(i, 1, n) { scanf("%d", &x); f(j, 1, 200)pr原创 2020-06-06 18:02:37 · 264 阅读 · 0 评论 -
C. Playlist(贪心)
题意:给一堆歌的集合,每首歌有长度和价值,求最多选k首歌的情况下,所有选的歌的长度*其中最小的价值的最大值。思路:对每首歌按价值大小从大到小排序,保证每次选择时,当前的价值是集合中最小的。struct node{ int t, b; bool operator<(const node b)const { if (this->b == b.b)return this->t > b.t; return this->b > b.b; }}e[N];in原创 2020-06-06 18:00:55 · 206 阅读 · 0 评论 -
D - Guess The Maximums(交互题)
理解:假设n=7,k=3,A=[1 5 3 7 2 6 4],按照题意将A划分为3个集合,s1=[1,4],s2=[2,5],s3=[3,6,7]。其中s1,s2,s3是所划分集合中元素的下标,对应的w1=[A[1]=1,A[4]=7],w2=[5,2],w3=[3,6,4]。求解:答案总共有为k个数字,从p1到pk,对于每个pi,当前的值是A[]中删去当前集合中所有下标所对应的值后的全局最大值。这里可以发现,如果A[]最大值MX不在当前的划分,那么当前的pi就是MX,否则就要模拟一次求解。所有,用1次查原创 2020-06-04 14:37:33 · 373 阅读 · 0 评论 -
D. The Best Vacation(尺取)
int a[N];ll d[N];int main() { ll n, x; while (cin >> n >> x) { f(i, 1, n) { scanf("%d", &a[i]); d[i] = (ll)a[i] * (1 + a[i]) / 2; } f(i, 1, n)a[n + i] = a[i], d[n + i] = d[i]; ll now = 0, now1 = 0; int l=n+1, r = n +原创 2020-05-27 01:36:58 · 301 阅读 · 0 评论 -
B. Circus(枚举)
对于每个角色有四种可能属性,a:10 b:01 c:11 d:00。思路:构造的情况要满足a1+c1==b2+c2,然后可以枚举第一层用到几个1,第二层枚举其中来自a的个数,然后移项推公式判断。。。。int main()//a:10 b:01 c:11 d:00 枚举:外层枚举第一次有几个人生效,内层枚举其中来自a的个数 然后推变量。。{ int n; string s1, s2; while (cin >> n >> s1 >> s2) { vec原创 2020-05-26 20:23:05 · 189 阅读 · 0 评论 -
H - Binary Median
const int N = 6e5 + 5;int t;int main(){ int n, m; cin >>t; string a; while (t--) { scanf("%d%d", &n, &m); unordered_set<ll> st; ll mid = (ll)pow(2, m) / 2 - 1; int fg = 1; f(i, 1, n) { cin >> a; ll sum =原创 2020-05-26 10:33:54 · 152 阅读 · 0 评论