2019银川区域赛BDFGHIKN题解
B.So Easy
题目大意:给你一个正方形矩阵,初始都是0,题目对这个矩阵做了许多次操作,每次操作把行+1或列+1.其中有一个元素被隐藏了,你需要找出这个被隐藏的元素并判断它在操作之后应该是多少。
做法:我们设被隐藏的数的下标为\(x,y\)。再设另一个数的下标为\(x_0,y_0(i\not=i_0,j\not=j_0)\),再设对行加了\(\{r_i\}\),对列加了\(\{c_i\}\)。那么可以得到下面四个式子。
\]
有了这四个式子接下来随便代一代消一消得到
\]
代码里选择\((1,1)\) 或 \((n,n)\)作为\((x_0,y_0)\)
#include<cstdio>
using namespace std;
const int N = 1000 + 3;
int a[N][N];
int main() {
int n,x,y;
scanf("%d",&n);
for(int i=1;i<=n;i++) {
for(int j=1;j<=n;j++) {
scanf("%d",&a[i][j]);
if(a[i][j] == -1) x=i,y=j;
}
}
int x0 = 1, y0 = 1;
if(x == 1 && y == 1) x0 = y0 = n;
printf("%d\n",a[x0][y]+a[x][y0]-a[x0][y0]);
return 0;
}
D. Easy Problem
题目大意:给出n,m,d,k请求出
\]
做法:莫比乌斯反演基础题。模拟赛的时候脑子抽了推成了别的东西。直接上式子。
\]
\]
\]
\]
\]
\]
推到这里就推完了。那么可以发现最后一项可以预处理,所以复杂度是\(O(m\log m)\)。log是快速幂的复杂度。
注意:在包含莫比乌斯函数的式子里,累加器可能加着加着就小于0了,记得把模数加上去。(找了两个小时的bugQAQ)。另外,这个模数不是质数,它的欧拉函数不是它减1.
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define IL inline
typedef long long LL;
const LL mod = 59964251;
const LL phim = 59870352;
const int N = 1e5 + 3;
int tot;
bool np[N];
int pri[N];
int mu[N];
IL void init_mu(int n) {
tot = 0;
mu[0] = 0;
np[1] = mu[1] = 1;
for(int i=2;i<=n;i++) {
if(!np[i]) { pri[tot++] = i; mu[i] = -1;}
for(int j=0;j<tot&&i*pri[j]<=n;j++) {
np[i*pri[j]] = true;
if(i%pri[j] == 0) {
mu[i*pri[j]] = 0;
break;
}
mu[i*pri[j]] = -mu[i];
}
}
}
IL LL ksm(LL a,LL b,LL p) {
LL res = 1;
while(b) {
if(b&1LL) res = res * a % p;
a = a * a % p;
b >>= 1LL;
}
return res;
}
LL n,m,d,k;
char s[N];
LL sumc[N];
int main() {
init_mu(1e5); int T; scanf("%d\n",&T);
while(T--) {
scanf("%s%lld%lld%lld\n",s,&m,&d,&k);
m /= d;
int len = strlen(s);
n = 0;
for(int i=0;i<len;i++) {
n = (n*10 + s[i] - '0') % phim;
}
sumc[0] = 0;
for(int i=1;i<=m;i++) sumc[i] = (sumc[i-1]+ksm(i,k,mod)) % mod;
LL ans = 0;
for(int i=1;i<=m;i++) {
ans = (ans + 1LL*mu[i]*ksm(i,n*k%phim+phim,mod)%mod*ksm(sumc[m/i],n+phim,mod)%mod + mod) % mod;
}
ans = ans * ksm(d,n*k%phim+phim,mod) % mod;
printf("%lld\n",ans);
}
return 0;
}
F. Function!
题目大意:给你n,求出$$\sum_{a=2}n(a\sum_{b=a}n \lfloor\log_ab\rfloor \lceil\log_ba\rceil)$$
做法:先看最右面一项,可以发现\(b>=a\),那么显然\(\lceil\log_ba\rceil=1\)。
那么式子化为$$\sum_{a=2}n(a\sum_{b=a}n \lfloor\log_ab\rfloor$$
接下来我们研究\(\lfloor\log_ab\rfloor\)这个函数的性质。
\]
接下来分情况讨论。
当\(a>\sqrt n\) 时,大于\(\sqrt n\)部分的求和变为$$\sum_{a=\sqrt{n}+1}^n a(n+1)-a2=(n+1)\sum_{a=\sqrt{n}+1}n a - \sum_{a=\sqrt{n}+1}na2$$ 这个式子利用平方和公式和等差数列求和,可以\(O(1)\)计算。
当\(a<=\sqrt n\) 时,这里我们枚举\(\lfloor\log_ab\rfloor\)的大小去计算答案。
总时间复杂度为\(O(\sqrt n \log n)\)
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
#define IL inline
typedef long long LL;
const LL mod = 998244353;
const LL inv2 = 499122177;
const LL inv6 = 166374059;
LL n;
IL LL he(LL a,LL b) {
a %= mod; b %= mod;
return (b*(b+1)%mod*inv2%mod - a*(a+1)%mod*inv2%mod + mod) % mod;
}
IL LL he2(LL a,LL b) {
a %= mod; b %= mod;
return (b*(b+1)%mod*(2*b+1)%mod*inv6%mod - a*(a+1)%mod*(2*a+1)%mod*inv6%mod + mod) % mod;
}
int main() {
scanf("%lld",&n);
int m = sqrt(n+0.5);
LL sum1 = 0, sum2 = 0;
for(int a=2;a<=m;a++) {
LL b = a;
int logab = 1;
for(;b<=n;logab++,b*=a) {
sum1 = (sum1 + 1LL*a*logab%mod*(min(b*a-1,n)-b+1)%mod) % mod;
}
}
sum2 = ((1+n)%mod*he(m,n)%mod - he2(m,n)%mod + mod) % mod;
printf("%lld\n",(sum1+sum2)%mod);
return 0;
}
G. Pot!!
题目大意:定义一种函数叫做pot.它的意义是\(pot_p(n)=m\),当且仅当\(p^m|n,p^{m+1} \not|n\)。p是质数。给你一个序列,初始值全为1.
有两种操作:
- 区间乘。把[l,r]所有数乘x。
- 输出$$\max_{l<=i<=r} { \max_{p|a_i} { pot_p(a_i) } } (1<=l<=r<=n)$$
做法:我们可以发现这道题x非常小,2~10.所以我们可以发现这里的p只有2,3,5,7.所以我们可以建四棵线段树,分别代表区间2,3,5,7最大的次数。这样我们就把区间乘改成了区间加。
模拟赛的时候抄了刘汝佳的板子,还是要改天把自己的pushdown版本印出来备用。
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define IL inline
typedef long long LL;
const int N = 1e5 + 3;
const int pri[] = {2,3,5,7};
const int ipri[] = {0,0,0,1,0,2,0,3};
struct SegmentTree {
int n;
int addv[4][N<<2];
int maxv[4][N<<2];
void build(int o,int L,int R) {
if(L == R) {maxv[0][o]=maxv[1][o]=maxv[2][o]=maxv[3][o]=0;return;}
int M = L + (R-L) / 2;
build(o<<1,L,M); build(o<<1|1,M+1,R);
for(int i=0;i<4;i++) maxv[i][o] = 0;
}
IL void init(int n){ this->n = n; build(1,1,n);}
IL void pushdown(int o,int L,int R) {
int M = L + (R-L) / 2;
for(int i=0;i<4;i++) {
maxv[i][o<<1] = maxv[i][o<<1] + addv[i][o];
maxv[i][o<<1|1] = maxv[i][o<<1|1] + addv[i][o];
addv[i][o<<1] = addv[i][o<<1] + addv[i][o];
addv[i][o<<1|1] = addv[i][o<<1|1] + addv[i][o];
addv[i][o] = 0;
}
}
int qL,qR,v[5];
void update(int o,int L,int R) {
if(qL <= L && R <= qR) {
for(int i=0;i<4;i++) {
maxv[i][o] += v[i];
addv[i][o] += v[i];
}
return;
}
pushdown(o,L,R);
int M = L + (R-L) / 2;
if(qL <= M) update(o<<1,L,M);
if(M < qR) update(o<<1|1,M+1,R);
for(int i=0;i<4;i++) {
maxv[i][o] = max(maxv[i][o<<1],maxv[i][o<<1|1]);
}
}
IL void upd(int L,int R,int x) {
v[0]=v[1]=v[2]=v[3] = 0;
for(int i=2;i<=x;i++) {
while(x % i == 0) {
v[ipri[i]]++;
x /= i;
}
}
qL = L; qR = R; update(1,1,n);
}
int pos;
int query(int o,int L,int R) {
if(qL <= L && R <= qR) return maxv[pos][o];
pushdown(o,L,R);
int M = L + (R-L) / 2, ans = 0;
if(qL <= M) ans = max(ans,query(o<<1,L,M));
if(M < qR) ans = max(ans,query(o<<1|1,M+1,R));
return ans;
}
IL int que(int L,int R) {
int ans = 0; qL = L; qR = R;
for(int i=0;i<4;i++) {
pos = i;
ans = max(ans,query(1,1,n));
}
return ans;
}
};
SegmentTree solver;
const int LEN = 20;
char s[LEN];
int main() {
int n,q;
scanf("%d%d\n",&n,&q);
solver.init(n);
while(q--) {
scanf("%s",s);
if(s[1] == 'U') { int l,r,x; scanf("%d%d%d\n",&l,&r,&x); solver.upd(l,r,x);}
else {
int l,r; scanf("%d%d\n",&l,&r);
printf("ANSWER %d\n",solver.que(l,r));
}
}
return 0;
}
H. Delivery Route
题目大意:给你一个无向图,无向图边权都为正。再给你一些有向边插进去,这些有向边可能边权为负。保证有向边之间不形成环,求源点到所有点的最短路。
做法:甚至出原题,甚至数据范围都不改。bzoj2200.
模拟赛的时候三个人各种换板子,上dij的3ms速度wa掉,上spfa的2000msT掉。
赛后写了一下spfa+slf的优化,过不去。在洛谷上交过了。
所以最后还是写了正解。
正解是先对无向图缩点,然后按照拓扑序去对这些点做dijkstra过程。而拓扑排序可以dfs也可以bfs,所以这里直接把拓扑排序和dijkstra结合在一起了。
注意:最后判断NO PATH的时候,不能判断\(d[i]>=INF\),因为有负权边,会更小,所以我直接写\(d[i]>=INF/2\)了...
#include<cstdio>
#include<cstring>
#include<vector>
#include<queue>
#include<deque>
#include<stack>
#include<algorithm>
using namespace std;
#define IL inline
typedef long long LL;
const int N = 25000 + 3;
const int INF = 1e9 + 3;
inline void read(int &x){
int s=0,w=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){s=(s<<3)+(s<<1)+(ch&15);ch=getchar();}
x=s*w;
}
void print(int x){
if(x<0) {
putchar('-');
x=-x;
}
if(x>=10)print(x/10);
putchar(x%10+'0');
}
struct Edge {
int u,v,w;
Edge(int u=0,int v=0,int w=0):u(u),v(v),w(w){}
};
struct HeapNode {
int d,u;
IL bool operator < (const HeapNode& rhs) const {
return d > rhs.d;
}
IL HeapNode(int d,int u):d(d),u(u){}
};
struct Dijkstra {
int n,m;
int scc_cnt;
vector<Edge> edges;
vector<int> G[N];
bool done[N];
int d[N];
int ru[N];
int belong[N];
IL void init(int n) {
this->n = n; scc_cnt = 0;
for(int i=0;i<n;i++) G[i].clear();
edges.clear();
}
IL void AddEdge(int u,int v,int w) {
edges.push_back(Edge(u,v,w));
m = edges.size();
G[u].push_back(m-1);
}
IL void dfs(int u) {
for(int i=0;i<G[u].size();i++) {
Edge &e = edges[G[u][i]];
int v = e.v;
if(belong[v]) continue;
belong[v] = belong[u];
dfs(v);
}
}
IL void dijkstra(int s) {
for(int i=0;i<n;i++) d[i] = INF;
d[s] = 0;
memset(done,0,sizeof(done));
priority_queue<HeapNode> q;
queue<int> sccq;
sccq.push(belong[s]);
for(int i=1;i<=scc_cnt;i++)
if(!ru[i]) sccq.push(i);
while(!sccq.empty()) {
int sccu = sccq.front(); sccq.pop();
for(int i=0;i<n;i++) {
if(belong[i]==sccu) q.push(HeapNode(d[i],i));
}
while(!q.empty()) {
HeapNode x = q.top(); q.pop();
int u = x.u;
if(done[u]) continue;
done[u] = true;
for(int i=0;i<G[u].size();i++) {
Edge &e = edges[G[u][i]];
int v = e.v, w = e.w;
if(d[v] > d[u] + w) {
d[v] = d[u] + w;
if(belong[u]==belong[v]) q.push(HeapNode(d[v],v));
}
if(belong[u]!=belong[v]&&--ru[belong[v]]==0) sccq.push(belong[v]);
}
}
}
}
IL void print() {
for(int i=0;i<n;i++) {
if(d[i] >= INF/2) printf("NO PATH\n");
else printf("%d\n",d[i]);
}
}
};
Dijkstra solver;
int main() {
//freopen("H.in","r",stdin);
//freopen("H.out","w",stdout);
int n,x,y,s;
read(n); read(x); read(y); read(s); s--;
solver.init(n);
for(int i=0;i<x;i++) {
int u,v,w; read(u); read(v); read(w); u--; v--;
solver.AddEdge(u,v,w);
solver.AddEdge(v,u,w);
}
for(int i=0;i<n;i++) {
if(!solver.belong[i]) { solver.belong[i]=++solver.scc_cnt; solver.dfs(i);}
}
for(int i=0;i<y;i++) {
int u,v,w; read(u); read(v); read(w); u--; v--;
solver.AddEdge(u,v,w);
solver.ru[solver.belong[v]]++;
}
solver.dijkstra(s);
solver.print();
return 0;
}
I. Base62
题目大意:进制转换
做法:我也不会,反正队友会就行了!(理直气壮)(以前听学长说他们同届的只会学习一点写代码能力的学怪连进制转换都不会写,我大声地嘲讽了他们。现在发现,原来我也不会。)T.T
贴上我照着队友的代码补题的代码。
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define IL inline
typedef long long LL;
const int N = 120 + 3;
int x,y;
char z[N];
int a[N];
int ans[N<<3];
IL int id(char c) {
if('0'<=c&&c<='9') return c - '0';
if('A'<=c&&c<='Z') return c - 'A' + 10;
if('a'<=c&&c<='z') return c - 'a' + 36;
}
int main() {
scanf("%d%d%s",&x,&y,z);
int len = strlen(z);
for(int i=0;i<len;i++) a[i] = id(z[i]);
int now = 0;
for(int i=0;i<len; ) {
for(int j=i;j<len-1;j++) {
a[j+1] += a[j] % y * x;
a[j] /= y;
}
ans[now++] = a[len-1] % y;
a[len-1] /= y;
while(i<len&&a[i]==0) i++;
}
for(int i=0;i<now;i++) {
int u = ans[now-i-1];
if(u <= 9) putchar(u+'0');
else if(u <= 35) putchar(u-10+'A');
else putchar(u-36+'a');
}
return 0;
}
K. Largest Common Submatrix
题目大意:给你两个nm矩阵,你要找出它们最大相同子矩阵。每个矩阵的元素的值从1~nm
做法:由于两个矩阵都是 1 到 nm 的排列,可以先做一个映射使得其中一个矩阵从上往下从左往右依次是 1 到 nm。这一步可参考最长公共子序列那个题的\(O(n \log n)\) 做法的第一步。
对于另一个矩阵的某个位置,如果左侧比它小 1,则认为左侧与它同色,如果上边比它小 m,则认为上边与它同色。
悬线法计算最大同色子矩阵即可。可以参考uvalive3029.
队友用神奇的做法A了这题,我也不知道是怎么A的。反正就是A了,我也懒得再写一遍悬线法。
把队友的代码丢上来。(做法与代码无关QWQ)
#include <bits/stdc++.h>
using namespace std;
const int N = 1e6 + 5, M = 1005;
struct Point {
int v, x, y;
}a[N], b[N], stck[M];
int A[M][M], B[M][M], t[M][M];
int top, ans;
int main() {
int n, m;
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
scanf("%d", &A[i][j]), a[A[i][j]].x = i, a[A[i][j]].y = j;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
scanf("%d", &B[i][j]), b[B[i][j]].x = i, b[B[i][j]].y = j;
for (int j = 1; j <= m; j++)
t[n][j] = 1;
for (int i = n - 1; i >= 1; i--) {
for (int j = 1; j <= m; j++)
if (A[i + 1][j] == B[b[A[i][j]].x + 1][b[A[i][j]].y])
t[i][j] = t[i + 1][j] + 1;
else t[i][j] = 1;
}
for (int i = 1; i <= n; i++) {
stck[++top] = (Point) {t[i][1], 1, 1};
ans = max(ans, t[i][1]);
for (int j = 2; j <= m; j++) {
int lstv = A[i][j - 1];
if (A[i][j] == B[b[lstv].x][b[lstv].y + 1]) {
Point tmp = (Point) {t[i][j], j, j};
while (top && stck[top].v >= t[i][j]) {
Point now = stck[top];
tmp.x = now.x;
ans = max(ans, now.v * (j - now.x));
top--;
}
stck[++top] = tmp;
}
else {
while (top) {
Point now = stck[top];
ans = max(ans, now.v * (j - now.x));
top--;
}
top = 0;
stck[++top] = (Point) {t[i][j], j, j};
ans = max(ans, t[i][j]);
}
}
while (top) {
Point now = stck[top];
ans = max(ans, now.v * (m - now.x + 1));
top--;
}
}
printf("%d", ans);
return 0;
}
N. Fibonacci Sequence
题目大意:1 1 2 3 5
做法:1 1 2 3 5
#include<cstdio>
int main() {
printf("1 1 2 3 5\n");
return 0;
}
你看这样就AC了8题,在银川,8题可是能出线啊!(震声)
2019银川区域赛BDFGHIKN题解的更多相关文章
- 2018-2019 ACM-ICPC 徐州区域赛 部分题解
题目链接:2018-2019 ACM-ICPC, Asia Xuzhou Regional Contest A. Rikka with Minimum Spanning Trees 题意: 给出一个随 ...
- 【2019银川网络赛】L:Continuous Intervals
题目大意:给定一个长度为 N 的序列,定义连续区间 [l, r] 为:序列的一段子区间,满足 [l, r] 中的元素从小到大排序后,任意相邻两项的差值不超过1.求一共有多少个连续区间. 题解:单调栈 ...
- 银川区域赛现场赛 Pot!!【线段树】
给定两个操作: MULTIPLY L R x 区间里都乘以一个数x MAX L R : 计算区间内一个2,3,5,7个数最大值. 思路:维护4个最大值.蓝瘦. /** 有 n 个数和 5 种操作 a ...
- ICPC2019上海区域赛 部分题解(正在更新)
K. Color Graph 题意: 给定一个简单图,点个数<=16,删去部分边后,使得该图中无边数为奇数得环,问剩下的边数最大为多少? 思路: 如果一个图中无奇数边的环,那么这个图一定是个二分 ...
- 银川区域赛 H道路与航线(原题啊)
按照<算法竞赛进阶指南>写的 哦对了,注意下最后判断,因为开始拓扑的时候,s可能不在里边,所以不一定等于INF,而是应该大于等于INF #include<cstring> #i ...
- 2019 ICPC 上海区域赛总结
2019上海区域赛现场赛总结 补题情况(以下通过率为牛客提交): 题号 标题 已通过代码 通过率 我的状态 A Mr. Panda and Dominoes 点击查看 5/29 未通过 B Prefi ...
- 【2013南京区域赛】部分题解 hdu4802—4812
上周末打了一场训练赛,题目是13年南京区域赛的 这场题目有好几个本来应该是我擅长的,但是可能是太久没做比赛了各种小错误代码写的也丑各种warusn trush搞得人很不爽 全场题之一的1002也没有想 ...
- 2014年亚洲区域赛北京赛区现场赛A,D,H,I,K题解(hdu5112,5115,5119,5220,5122)
转载请注明出处: http://www.cnblogs.com/fraud/ ——by fraud 下午在HDU上打了一下今年北京区域赛的重现,过了5题,看来单挑只能拿拿铜牌,呜呜. ...
- Comet OJ 2019 夏季欢乐赛题解
Comet OJ 2019 夏季欢乐赛题解 我是来骗访问量的 A 完全k叉树 \(n\)个点的完全k叉树的直径. 直接做 B 距离产生美 直接做 C 烤面包片 \(n!!!\mod p\) 显然\(n ...
- 2019ICPC区域赛(银川)总结
2019ICPC银川 作为第一次打区域赛的我,心情异常激动,加上学校给坐飞机(事实上赶飞机很痛苦). 热身赛很难受,oj上不去,写AC自动机输入没写好.. 现场赛,开场直觉倒着看,发现签到.然后看B, ...
随机推荐
- dotnet 读 WPF 源代码笔记 WPF 是如何做到一套代码兼容多个 .NET Framework 版本
在 .NET Framework 时代里面,有一组有趣的概念,那就是 SDK 和 Runtime 这两个概念.开发模式十分有趣,在开发者设备上,可以指定 .NET Framework 的 SDK 版本 ...
- C# dotnet 的锁 SemaphoreSlim 和队列
本文主要是试验在顺序进入等待 SemaphoreSlim 的任务是否会按照顺序经过锁执行 我在一个有趣的WPF程序里面,需要限制任务同时执行的线程数量,不然用户就会说用我的程序会让电脑卡渣.而我的任务 ...
- h5开发,原生开发,混合开发
这里做一点对h5开发,原生开发,混合开发的笔记,记一点更新一点: 一.h5开发:html,css和js编写页面和业务逻辑. 1..页面栈上,h5通过history来管理回退或者前进.vue通过配置路由 ...
- CF620E New Year Tree (线段树维护 dfs 序)
CF620E New Year Tree 题意:给出一棵 n 个节点的树,根节点为 1.每个节点上有一种颜色 ci.m 次操作.操作有两种: 1 u c:将以 u 为根的子树上的所有节点的颜色改为 ...
- 11.IO 流
1.IO 流引入 概述:以应用程序为参照物,读取数据为输入流(Input),写数据为输出流(Output),大量输入输出数据简称 IO 流 原理: 2.IO 流的分类 读写的文件分类 二进制文件:打开 ...
- 超轻量级的c#版基于文件的日志记录工具,可定制输出格式,可指定日志文件
这是我自己个人编写的日志记录,主要使用在只需要记录日志,偶尔到文件中查看一下日志记录的情况.我自己写的一些服务之类的是使用了这个的,代码很少,使用很简单. 第一步 搜索和安装我的Nuget包 搜索和安 ...
- iptables命令详解
安装iptables yum install iptables-services 编写允许访问的策略 vim /etc/sysconfig/iptables # sample configuratio ...
- Oracle中ALTER TABLE的五种用法(四、五)
首发微信公众号:SQL数据库运维 原文链接:https://mp.weixin.qq.com/s?__biz=MzI1NTQyNzg3MQ==&mid=2247485212&idx=1 ...
- Python:Python字符串中的r、u和转义字符
Python中字符串前面我们经常看到加r(R)或u/(U)的前缀,而这两个符号是什么意思呢? 1.r(R) r意为raw,表示不包含转义字符的原生字符串.常见的转义字符包括下列几种: 转义字符 描述 ...
- 什么是Java线程池
摘自:某个百度知道 多线程技术主要解决处理器单元内多个线程执行的问题,它可以显著减少处理器单元的闲置时间,增加处理器单元的吞吐能力. 假设一个服务器完成一项任务所需时间为:T1 创建线程时间,T2 在 ...