【CF】Codeforces Round #536 (Div. 2)
cf改题计划
cf round 536 div 2
A 水题模拟
#include<cstdio>
#include<algorithm>
#include<iostream>
using namespace std;
const int maxn = 505;
char s[505][505];
int n;
int cnt;
int main() {
scanf("%d",&n);
for(int i=1;i<=n;i++) {
scanf("%s",&s[i][1]);
}
for(int i=1;i<=n;i++) {
for(int j=1;j<=n;j++) {
if(s[i][j]=='X'&&s[i-1][j-1]=='X'&&s[i+1][j+1]=='X'&&s[i-1][j+1]=='X'&&s[i+1][j-1]=='X')cnt++;
}
}
printf("%d",cnt);
}
B 真 模拟
用个set照着题目做就可以了
#include<cstdio>
#include<algorithm>
#include<iostream>
#include<set>
#define pr pair<int,int>
#define int long long
using namespace std;
const int maxn = 2e5+5;
int n,m;
int A[maxn],C[maxn];
struct node{
int co,nm,dy;
};
bool operator<(node aa,node bb) {
if(aa.co!=bb.co) return aa.co < bb.co;
if(aa.nm!=bb.nm) return aa.nm < bb.nm;
return aa.dy < bb.dy;
}
set<node>se;
main() {
scanf("%I64d%I64d",&n,&m);
for(int i=1;i<=n;i++) {
scanf("%I64d",&A[i]);
}
for(int i=1;i<=n;i++) {
scanf("%I64d",&C[i]);
se.insert((node){C[i],A[i],i});
}
for(int i=1;i<=m;i++) {
int ans = 0;
int t,d; scanf("%I64d%I64d",&t,&d);
if(!se.size()) {
puts("0"); continue;
}
int o = min(d,A[t]); d-=o;
ans += o*C[t];
se.erase((node){C[t],A[t],t});
A[t]-=o;
if(A[t]>0) se.insert((node){C[t],A[t],t});
while(d>0&&se.size()) {
node tmp = *se.begin();
se.erase(tmp);
o = min(tmp.nm,d);
d-=o; tmp.nm-=o; A[tmp.dy]-=o;
ans += o*tmp.co;
if(tmp.nm>0) se.insert(tmp);
}
if(d==0)printf("%I64d\n",ans);
else puts("0");
}
}
C 真 水题模拟。。。先做B的我悔恨不已
#include<stdio.h>
#include<iostream>
#include<cstdio>
#include<algorithm>
#define int long long
using namespace std;
const int maxn = 3e5+5;
int n;
int a[maxn];
main() {
scanf("%I64d",&n);
for(int i=1;i<=n;i++) {
scanf("%I64d",&a[i]);
}
sort(a+1,a+n+1);
int ans = 0;
for(int i=1,j=n;i<j;i++,j--) {
ans = ans + (a[i]+a[j])*(a[i]+a[j]);
}
printf("%I64d",ans);
}
D 直接BFS一下,把下步可以到的点加入小根堆,模拟就可以了。
\#include<iostream>
#include<algorithm>
#include<cstdio>
#include<vector>
#include<queue>
using namespace std;
const int maxn = 2e5+5;
vector<int>ve[maxn];
priority_queue<int,vector<int>,greater<int> >q;
int n,m;
bool mk[maxn];
int main() {
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++) {
int x,y; scanf("%d%d",&x,&y);
ve[x].push_back(y); ve[y].push_back(x);;
}
q.push(1);
while(q.size()) {
int x = q.top(); q.pop();
if(mk[x]) continue;
mk[x] = 1;
printf("%d ",x);
for(auto y:ve[x]) {
if(!mk[y]) q.push(y);
}
}
}
E 搞出扫描线之后f[i][j]时间i,打扰了j次可以得到最少金钱,顺着DP就可以了。
#include<stdio.h>
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<set>
#include<cstring>
#define int long long
using namespace std;
const int maxn = 1e5+5;
int f[205][maxn];
struct node{
int tm,d,co;
int op;
}z[maxn*2]; int tot;
bool operator<(node aa,node bb) {
if(aa.co!=bb.co) return aa.co > bb.co;
return aa.d > bb.d;
}
bool cmp(node aa,node bb) {
if(aa.tm!=bb.tm) return aa.tm < bb.tm;
return aa.op < bb.op;
}
multiset<node>se;
int n,m,k;
main() {
scanf("%I64d%I64d%I64d",&n,&m,&k);
memset(f,0x3f,sizeof f);
f[m][1] = 0;
for(int i=1;i<=k;i++) {
int s,t,d,w; scanf("%I64d%I64d%I64d%I64d",&s,&t,&d,&w);
++tot; z[tot].tm = s; z[tot].op = 1; z[tot].d = d; z[tot].co = w;
++tot; z[tot].tm = t+1; z[tot].op = -1; z[tot].d = d; z[tot].co = w;
}
sort(z+1,z+1+tot,cmp);
int now = 1;
for(int t=1;t<=n;t++) {
while(now<=tot&&z[now].tm<=t) {
if(z[now].op==1) {
se.insert(z[now]);
} else {
z[now].op = 1;
se.erase(se.lower_bound(z[now]));
}
now++;
}
if(se.size()) {
node tmp = *se.begin();
if(f[0][t]!=f[0][0])
f[0][tmp.d+1] = min(f[0][tmp.d+1],f[0][t]+tmp.co);
for(int i=1;i<=m;i++) {
if(f[i][t]!=f[0][0]) {
f[i][tmp.d+1] = min(f[i][tmp.d+1],f[i][t]+tmp.co);
f[i-1][t+1] = min(f[i][t],f[i-1][t+1]);
}
}
} else {
for(int i=0;i<=m;i++) {
f[i][t+1] = min(f[i][t+1],f[i][t]);
}
}
}
int ans = 1e18;
for(int i=0;i<=m;i++) ans = min(ans,f[i][n+1]);
printf("%I64d",ans);
}
F 矩阵乘法很好想到,,,主要问题是在mod 998244353意义下已知b,k求x^k == b 的x.(即k次剩余)
由于有原根,那么g^(r * k ) == g ^ o 已知k,o,求r,那么
r * k == o (mod p-1),利用扩欧解一下这个方程,能解出来就OK,解不出来就无解。
对于中间求o要用BSGS
O(k^3logn + sqrt(998244353) )
具体见:
codeforces1106F