Codeforces 888 - A/B/C/D/E - [数学题の小合集]
这次CF不是很难,我这种弱鸡都能在半个小时内连A四道……不过E题没想到还有这种折半+状压枚举+二分的骚操作,后面就挂G了……
A.Local Extrema
题目链接:https://cn.vjudge.net/problem/CodeForces-888A
You are given an array a. Some element of this array ai is a local minimum iff it is strictly less than both of its neighbours (that is, ai < ai - 1 and ai < ai + 1). Also the element can be called local maximum iff it is strictly greater than its neighbours (that is, ai > ai - 1 and ai > ai + 1). Since a1 and an have only one neighbour each, they are neither local minima nor local maxima.
An element is called a local extremum iff it is either local maximum or local minimum. Your task is to calculate the number of local extrema in the given array.
Input
The first line contains one integer n (1 ≤ n ≤ 1000) — the number of elements in array a.
The second line contains n integers a1, a2, ..., an (1 ≤ ai ≤ 1000) — the elements of array a.
Output
Print the number of local extrema in the given array.
Example
3
1 2 3
0
4
1 5 2 5
2
AC代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<bits/stdc++.h> using namespace std; int n,num[1005],cnt; bool local_extremum(int a,int b,int c){return (a<b && b>c)||(a>b && b<c);} int main() { cin>>n; for(int i=1;i<=n;i++) scanf("%d",&num[i]); cnt=0; for(int i=2;i<=n-1;i++) { if(local_extremum(num[i-1],num[i],num[i+1])) cnt++; } cout<<cnt<<endl; }
B.Buggy Robot
题目链接:https://cn.vjudge.net/problem/CodeForces-888B
Ivan has a robot which is situated on an infinite grid. Initially the robot is standing in the starting cell (0, 0). The robot can process commands. There are four types of commands it can perform:
- U — move from the cell (x, y) to (x, y + 1);
- D — move from (x, y) to (x, y - 1);
- L — move from (x, y) to (x - 1, y);
- R — move from (x, y) to (x + 1, y).
Ivan entered a sequence of n commands, and the robot processed it. After this sequence the robot ended up in the starting cell (0, 0), but Ivan doubts that the sequence is such that after performing it correctly the robot ends up in the same cell. He thinks that some commands were ignored by robot. To acknowledge whether the robot is severely bugged, he needs to calculate the maximum possible number of commands that were performed correctly. Help Ivan to do the calculations!
Input
The first line contains one number n — the length of sequence of commands entered by Ivan (1 ≤ n ≤ 100).
The second line contains the sequence itself — a string consisting of n characters. Each character can be U, D, L or R.
Output
Print the maximum possible number of commands from the sequence the robot could perform to end up in the starting cell.
Example
4
LDUR
4
5
RRRUU
0
6
LLRRRR
4
题意:
机器人可以Up,Down,Left,Right四个方向移动一格;
现在给出一系列移动指令,因为规定了机器人肯定能在执行完这一系列指令后能回到原点,所以着一系列指令中必然有些是无效指令;
求最大有效指令是多少个;
题解:
一个U跟一个D抵消,一个L和一个R抵消,对它们计数一下在再计算一下即可。
AC代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<bits/stdc++.h> using namespace std; int n,cnt[5]; char mov[105]; int main() { cin>>n; scanf("%s",mov+1); memset(cnt,0,sizeof(cnt)); for(int i=1;i<=n;i++) { if(mov[i]=='U') cnt[1]++; else if(mov[i]=='D') cnt[2]++; else if(mov[i]=='L') cnt[3]++; else if(mov[i]=='R') cnt[4]++; } int ans=2*min(cnt[1],cnt[2])+2*min(cnt[3],cnt[4]); cout<<ans<<endl; }
C.K-Dominant Character
题目链接:https://cn.vjudge.net/problem/CodeForces-888C
You are given a string s consisting of lowercase Latin letters. Character c is called k-dominant iff each substring of s with length at least k contains this character c.
You have to find minimum k such that there exists at least one k-dominant character.
Input
The first line contains string s consisting of lowercase Latin letters (1 ≤ |s| ≤ 100000).
Output
Print one number — the minimum value of k such that there exists at least one k-dominant character.
Example
abacaba
2
zzzzz
1
abcde
3
题意:
给定一个小写字母串s,对某个字母c,如果对于s的所有长度为k的子串,都含有c,就称字符c为k-Dominant;
对字符串中的所有字母,求其k,求其中最小的。
题解:
求出字符串s中某个字符c的前后差距的最大值,即k;
例如:abacaba中的字符a;
s[1]='a',与前面(位置为0)差距为1(1-0=0),与后面的a差距为2(3-1=2);
s[3]='a',与前面(位置为1)差距为2(3-1=2),与后面的a差距为2(5-3=2);
……
s[7]='a',与前面(位置为5)差距为2(7-5=2),与后面差距(len+1)为1(7+1-7=1);
所以字符a对应的k为2;
对字符串s中每个字符都算出k,取其中最小的即可。
AC代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<bits/stdc++.h> using namespace std; int inte[30],last[30]; char str[100000+5]; int main() { scanf("%s",str+1); int len=strlen(str+1); memset(inte,0,sizeof(inte)); memset(last,0,sizeof(last)); for(int i=1;i<=len;i++) { int id=str[i]-'a'; inte[id]=max(inte[id],i-last[id]); last[id]=i; } for(int i=0;i<26;i++) { if(inte[i]==0) continue; inte[i]=max(inte[i],len+1-last[i]); } int ans=0x3f3f3f3f; for(int i=0;i<26;i++) { if(inte[i]==0) continue; ans=min(ans,inte[i]); } cout<<ans<<endl; }
D.Almost Identity Permutations
题目链接:https://cn.vjudge.net/problem/CodeForces-888D
A permutation p of size n is an array such that every integer from 1 to n occurs exactly once in this array.
Let's call a permutation an almost identity permutation iff there exist at least n - k indices i (1 ≤ i ≤ n) such that pi = i.
Your task is to count the number of almost identity permutations for given numbers n and k.
Input
The first line contains two integers n and k (4 ≤ n ≤ 1000, 1 ≤ k ≤ 4).
Output
Print the number of almost identity permutations for given n and k.
Example
4 1
1
4 2
7
5 3
31
5 4
76
题意:
对于一个1~n的序列,给定一个k,如果它的全排列中某一个排列,它至少有n-k个pi=i,就称其为almost identity permutation;
求almost identity permutation数目。
题解:
观察到1<=k<=4,所以我们可以分而治之;
先比如求出 n-1个pi=i 的排列有几个,在求n-2的,直到n-k,在全部加起来即可;
AC代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<bits/stdc++.h> using namespace std; int n,k; long long ans; long long C[1001][1001]; void calc_Cmn()//求组合数 { for(int i=0;i<1001;i++) { C[i][0]=C[i][i]=1; for(int j=1;j<i;j++) C[i][j]=C[i-1][j-1]+C[i-1][j]; } } int main() { calc_Cmn(); cin>>n>>k; for(int i=n-1;i>=n-k;i--) { if(i==n-1) ans+=1; if(i==n-2) ans+=C[n][i]; if(i==n-3) ans+=C[n][i]*2; if(i==n-4) ans+=C[n][i]*9; } cout<<ans<<endl; }
E.Maximum Subsequence
题目链接:https://cn.vjudge.net/problem/CodeForces-888E
You are given an array a consisting of n integers, and additionally an integer m. You have to choose some sequence of indices b1, b2, ..., bk (1 ≤ b1 < b2 < ... < bk ≤ n) in such a way that the value of is maximized. Chosen sequence can be empty.
Print the maximum possible value of .
Input
The first line contains two integers n and m (1 ≤ n ≤ 35, 1 ≤ m ≤ 109).
The second line contains n integers a1, a2, ..., an (1 ≤ ai ≤ 109).
Output
Print the maximum possible value of .
Example
4 4
5 2 4 1
3
3 20
199 41 299
19
题解:
拆成两半,枚举前半部分的所有状态,算出sum,存起来,记为l_sum[];
枚举后半部分状态,每算出一个sum,去l_sum[]里二分查找能和它加起来最大的,又不会超过m-1的;
AC代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<bits/stdc++.h> typedef long long ll; using namespace std; int n,mid; ll num[40],MOD; ll l_sum[131100]; int _size=0; ll bisearch(ll limit)//在l_sum[]中查找小于等于limit的最大值 { //printf("limit is %lld\n",limit); int l=0,r=_size-1,mid; while(l<=r) { mid=(l+r)/2; //printf("now l=%d r=%d %lld\n",l,r,l_sum[mid]); if(l_sum[mid]==limit) return limit; if(l_sum[mid]>limit) r=mid-1; else l=mid+1; } return l_sum[l-1]; } int main() { cin>>n>>MOD; mid=n/2; for(int i=1;i<=n;i++) cin>>num[i],num[i]%=MOD; for(int state=0;state<(1<<mid);state++) { ll sum=0; for(int cnt=1,sta=state;sta>0;cnt++) { sum+=(sta&1)*num[cnt]; sta=(sta>>1); } l_sum[_size++]=sum%MOD; } sort(l_sum,l_sum+_size); _size=unique(l_sum,l_sum+_size)-l_sum; //for(int i=0;i<_size;i++) cout<<l_sum[i]<<endl;cout<<endl; ll ans=-1; for(int state=0;state<(1<<(n-mid));state++) { ll sum=0; for(int cnt=mid+1,sta=state;sta>0;cnt++) { sum+=(sta&1)*num[cnt]; sta=(sta>>1); } sum%=MOD; ans=max(ans,sum+bisearch(MOD-1-sum)); if(ans==MOD-1) break; } cout<<ans<<endl; }