【CF】Educational Codeforces Round 60 (Rated for Div. 2)
好累好累,感冒了,十分难受。
A水题模拟
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<iostream>
#include<cstring>
#include<queue>
#include<stack>
#include<vector>
using namespace std;
int n;
int a[100005];
int mx=-1;
int ans = 0;
int ff;
int main() {
scanf("%d",&n);
for(int i=1;i<=n;i++) {
scanf("%d",&a[i]);
mx = max(mx,a[i]);
}
for(int i=1;i<=n;i++) {
if(a[i]==mx) ff++;
else ff=0;
ans = max(ans,ff);
}
cout<<ans;
}
B水题模拟
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<iostream>
#include<cstring>
#include<queue>
#include<stack>
#include<vector>
#define int long long
using namespace std;
int n,m,k;
int a[200005];
int MX=-1,MI=-1;
main() {
scanf("%I64d%I64d%I64d",&n,&m,&k);
for(int i=1;i<=n;i++) {
scanf("%I64d",&a[i]);
if(a[i]>MX) MI=MX,MX=a[i];
else if(a[i]>MI) MI=a[i];
}
int ans = 0;
ans+=(MX*k+MI)*(m/(k+1));
m%=(k+1);
ans += m*MX;
cout<<ans;
}
C
有一天气预报会告知每天的风将会将你向上下左右中某个方向吹一个单位长度,每天你可以根据自主意愿向上下左右任意方向移动一个单位,也可以不动,给出一个初始坐标和一个终点目标,问最少需要多少天到达目标地点
二分一个答案之后看直接根据风向会到哪里,然后比较当前到终点距离和天数。
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<iostream>
#include<cstring>
#include<queue>
#include<stack>
#include<vector>
#define int long long
using namespace std;
int xa,ya,xb,yb;
int n;
char ss[100005];
int sx[100005],sy[100005];
bool ok(int mid) {
int xo = xa + (mid/n)*sx[n] + sx[mid%n];
int yo = ya + (mid/n)*sy[n] + sy[mid%n];
if(abs(xo-xb)+abs(yo-yb)<=mid) return 1;
return 0;
}
main() {
scanf("%I64d%I64d%I64d%I64d%I64d",&xa,&ya,&xb,&yb,&n);
scanf("%s",&ss[1]);
for(int i=1;i<=n;i++) {
sx[i] = sx[i-1]; sy[i] = sy[i-1];
if(ss[i]=='U') sy[i]++;
if(ss[i]=='D') sy[i]--;
if(ss[i]=='L') sx[i]--;
if(ss[i]=='R') sx[i]++;
}
int L = 0; int R = 1e14+5,mid,ans;
ok(5);
if(!ok(R)) {
puts("-1"); return 0;
}
while(L<=R) {
mid = (L+R)>>1;
if(ok(mid)) R = mid - 1,ans=mid;
else L = mid + 1;
}
printf("%I64d",ans);
}
D补。。可能矩乘太差了
现有一些魔法细菌,他们可以变成m个普通细菌,普通细菌不能变化.问有多少种方式选出一定数量的魔法细菌并使其中一部分分裂,使得最终的细菌数量为n
f[n] = f[n-1] + f[n-m],直接上一个矩乘就好啦
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<iostream>
#include<cstring>
#include<queue>
#include<stack>
#include<vector>
#define int long long
using namespace std;
const int mod = 1e9+7;
struct mat{
int o[105][105];
}A,f;
int n,m;
int add(int x,int y){ x+=y; return x>=mod?x-mod:x; }
int sub(int x,int y){ x-=y; return x<0?x+mod:x; }
int mul(int x,int y){ return 1ll*x*y%mod; }
mat operator*(mat aa,mat bb) {
static mat tmp;
for(int i=0;i<m;i++) {
for(int j=0;j<m;j++) {
int oo = 0;
for(int k=0;k<m;k++) {
oo = add(oo,mul(aa.o[i][k],bb.o[k][j]));
}
tmp.o[i][j]=oo;
}
}
return tmp;
}
void ksm(int b) {
for(;b;b>>=1,f=f*f)
if(b&1) A = A*f;
}
main() {
scanf("%I64d%I64d",&n,&m);
for(int i=1;i<m;i++) {
f.o[i-1][i]++;
}
f.o[0][0]++;f.o[m-1][0]++;
A.o[0][0]++;
ksm(n);
printf("%I64d",A.o[0][0]);
}
E补
给出你一个变换过的字符串,你可以进行三次询问,每次询问给出一个字符串,其将对你进行询问的字符串进行相同的变换,问一开始给出的字符串的初始字符串长度10000
比较显然想法如果一共只有26位字符,那么可以直接代入然后定位。
由于我们有三次询问,意味着我们可以组成26^3种字符串代入进去。
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<map>
using namespace std;
int n;
map<string,int>dy;
string T,mj[10005];
string a[4];
char ss[10005];
void fl() {
fflush(stdout);
}
void dfs(int x,string now) {
mj[x] = now;
dy[now] = x;
if(x==n) return;
now[0]++;
if(now[0]=='z'+1) now[1]++,now[0]='a';
if(now[1]=='z'+1) now[2]++,now[1]='a';
dfs(x+1,now);
}
string ts(string a) {
swap(a[0],a[1]);
swap(a[1],a[2]);
return a;
}
int main() {
cin>>T;
n = T.size();
dfs(1,"aaa");
for(int i=1;i<=3;i++) {
cout<<"? ";
string yooo;
for(int j=1;j<=n;j++) yooo+=mj[j][i-1];
cout<<yooo<<endl;
fl();
cin>>a[i];
//a[i] = ts(yooo);
}
for(int i=1;i<=n;i++) {
string orz;
orz.push_back((char)a[1][i-1]);
orz.push_back((char)a[2][i-1]);
orz.push_back((char)a[3][i-1]);
int o = dy[orz];
ss[o-1]+=T[i-1];
}
cout<<"! "<<ss<<endl;
fl();
}
F 补
给你一个'a'到'a'+17的1e5的字符串,然后给你一个17 * 17的矩阵,含义为对应的字母始终不能相邻。你可以按照你自己的顺序去除一种字符(满足矩阵),然后求可以得到的字符串的最小的剩余字符数。
考虑我们枚举每个矩阵中的0,如果矩阵(x,y)为0,那么我们暴力扫一遍,找出其中的字符为(x,y)的区间,那么意味着不能在x,y都在的时候,消除x,y之间的所有字符种类,我们状压一下之后,把这些不能同时消除的状态记录下来。最后暴力状压dp枚举一下就可以了。
#include<stdio.h>
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
using namespace std;
const int maxn = 2e5+5;
int S;
bool BJ[1<<18];
int A[maxn];
int n,p;
char ss[maxn];
void gaogao(int x,int y) {
int lst = 0;
for(int i=1;i<=n;i++) {
if(A[lst]==x&&A[i]==y) {
int orz = (1<<(x-1))|(1<<(y-1));
int YO = S^orz; BJ[orz] = 1;
for(int j=lst+1;j<i;j++) YO &= (S^(1<<(A[j]-1)));
for(int o=YO;o;o = (o-1)&YO) BJ[orz|o] = 1;
}
if(A[i]==x||A[i]==y) lst = i;
}
}
int ANS;
int cnt[maxn];
void dfs(int s,int cc) {
if(BJ[s]) return; BJ[s] = 1;
ANS = min(ANS,cc);
for(int i=1;i<=p;i++) {
if((1<<(i-1))&s) dfs(s^(1<<(i-1)),cc-cnt[i]);
}
}
int main() {
scanf("%d%d",&n,&p);
S = (1<<p)-1;
scanf("%s",&ss[1]);
for(int i=1;i<=n;i++) {
A[i] = ss[i]-'a'+1;
cnt[A[i]]++;
}
for(int i=1;i<=p;i++) {
for(int j=1;j<=p;j++) {
int x; scanf("%d",&x);
if(!x) {
gaogao(i,j);
}
}
}
ANS = n; dfs(S,n);
printf("%d",ANS);
}
G 给你一个n = 1e6的序列(序列中的数pi<=n),对于一个询问$L$,$R$,会得到f(L,R),设$mx$为$[L,R]$中的最大值的位置,$ f(L,R) = (R-L+1)+ f(L,mx-1) + f(mx+1,R) $, 如果$ L>R , f(L,R) = 0 $。询问数<=1e6
我们考虑对于每一个,$i$对$f(l,r)$的贡献,设$le[i]$为其左边第一个比他大的数的位置,$ri[i]$为其右边第一个比他大的数的位置,那么$ f(l,r) = min(ri[i]-1,r) - max(le[i]+1,l)+1 $,为方便计算,离线之后,对于一个i我们我们可以将问题拆开成算$[le[i],i]$的贡献和$[i+1,ri[i]]$两部分,然后答案加起来,这样的话,我们就可以只用考虑前缀或者只用考虑后缀,并且不会算到在区间外别的元素给予的多余的贡献。
口胡就好,不想写啦!