终于到了饭吉圆杯的开赛,这是EZ我参与的历史上第一场ACM赛制的题目然而没有罚时

不过题目很好,举办地也很成功,为法老点赞!!!

这次和翰爷,吴骏达 dalao,陈乐扬dalao组的队,因为我们有二个初二的,所以并起来算一个 。

然后我和另外一个初二的连键盘都没摸,靠着翰爷的大杀四方成功A了5题并因为罚时惜败得到Rank2。%%%Orz 翰爷%%%

好了下面开始讲题。饭吉圆链接

与一般的ACM相似,这次考试的题目也分为三档

  • Easy:NOIp普及组+难度(法老认为);NOIp提高组T1,T2难度(我认为)
  • Medium:比较套路略加一点思维的NOIp提高组题 (法老认为);NOIpT3+至弱省省选题(我认为)
  • Hard: 省选常见算法题,难度略低于省选(法老认为);ZJOI/HNOI省选题+NOI-神题(我认为)

好了我是真的菜,并且针对我无比菜的水平,我也只改了Easy+Medium。

Easy(难度递增)

I. 「QZEZ第一届“饭吉圆”杯程序设计竞赛」画展

整场比赛最水的题目了,模拟题不解释。

由于\(n\le 111\),因此连Hash都不用上。我们直接把图变成字符串然后开Map存一下即可

CODE

#include<iostream>
#include<cstdio>
#include<map>
#include<string>
using namespace std;
const int N=120;
map <string,bool> t;
int n,m,a,b,ans;
char g[N][N];
bool vis[N][N];
string s;
inline void find(void)
{for (register int i=2;i<=n;++i)if (g[i][2]=='#') { a=i-2; break; }for (register int i=2;i<=m;++i)if (g[2][i]=='#') { b=i-2; break; }
}
inline void solve(int x1,int y1,int x2,int y2)
{register int i,j;for (s="",i=x1;i<=x2;++i)for (j=y1;j<=y2;++j)s+=g[i][j],vis[i][j]=1;if (t[s]) return;for (s="",i=x2;i>=x1;--i)for (j=y2;j>=y1;--j)s+=g[i][j];if (t[s]) return;if (a==b){for (s="",j=y2;j>=y1;--j)for (i=x1;i<=x2;++i)s+=g[i][j];if (t[s]) return;for (s="",j=y1;j<=y2;++j)for (i=x2;i>=x1;--i)s+=g[i][j];if (t[s]) return;}t[s]=1; ++ans;
}
int main()
{//freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout);register int i,j; ios::sync_with_stdio(false); cin>>n>>m;for (i=1;i<=n;++i)for (j=1;j<=m;++j)cin>>g[i][j]; find();for (i=1;i<=n;++i)for (j=1;j<=m;++j)if (g[i][j]!='#'&&!vis[i][j]) solve(i,j,i+a-1,j+b-1);return printf("%d",ans),0;
}

F. 「QZEZ第一届“饭吉圆”杯程序设计竞赛」数学作业

这道题有两种方法。

第一种当然是暴力证明了,由于我不会,因此给出法老的手写证明

第二种就比较策略了。题目中提到了:

\(f(s)\)的函数图像似乎是一个极其诡异的曲线

然后我们根据相似三角形感性理解一下其实面积变大的话其形状不会改变,只有边长会按比例增加。

因此我们可以结合样例得到:

\(f(s)=A \sqrt S=1.63299\sqrt S\)

然后写上去一交发现WA了!Why?精度!

我们来猥琐一波:

\((1.63299)^2=2.666...=\frac{8}{3}\)

所以\(A=\frac{2\sqrt S}{3}\)

然后就水过了。

CODE

#include<cstdio>
#include<cmath>
using namespace std;
int main()
{int n; scanf("%d",&n);printf("%.5lf",(double)sqrt(n*8.0/3.0));return 0;
}

B. 「QZEZ第一届“饭吉圆”杯程序设计竞赛」最小完美生成树

也是比较简单的题目,要正确理解题意

首先我们先对原图跑一遍MST,如果求出来的MST已经包含多种颜色,那么直接输出答案即可。

如果只有一种颜色,我们就挑一条不同颜色的边,然后肯定会有一条边被替换下来。

我们找到这条边的最大值即可。

这种方法可以和求LCA一起搞,主要就是倍增。

令\(f_{i,j}\)表示第\(i\)条边向上\(2^j\)次步的路径上的最大值,然后和LCA一起做即可(因为刚好也查询到LCA)

具体维护看CODE

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=100005,P=20;
struct edge
{int to,next,v;
}e[N<<1];
struct data
{int l,r,w,col;bool use;
}a[N];
int head[N],n,m,pa[N][P],f[N][P],father[N],dep[N],cnt,c,rt=1;
long long tot;
inline char tc(void)
{static char fl[100000],*A=fl,*B=fl;return A==B&&(B=(A=fl)+fread(fl,1,100000,stdin),A==B)?EOF:*A++;
}
inline void read(int &x)
{x=0; char ch=tc();while (ch<'0'||ch>'9') ch=tc();while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=tc();
}
inline bool comp(data a,data b)
{return a.w<b.w;
}
inline void add(int x,int y,int z)
{e[++cnt].to=y; e[cnt].v=z; e[cnt].next=head[x]; head[x]=cnt;
}
inline int max(int a,int b)
{return a>b?a:b;
}
inline int min(int a,int b)
{return a<b?a:b;
}
inline int getfather(int k)
{return father[k]==k?k:father[k]=getfather(father[k]);
}
inline void DFS(int now,int fa)
{for (register int i=head[now];i!=-1;i=e[i].next)if (e[i].to!=fa) f[e[i].to][0]=e[i].v,pa[e[i].to][0]=now,dep[e[i].to]=dep[now]+1,DFS(e[i].to,now);
}
inline void init(void)
{for (register int j=0;j<P-1;++j)for (register int i=1;i<=n;++i)if (pa[i][j]) pa[i][j+1]=pa[pa[i][j]][j],f[i][j+1]=max(f[i][j],f[pa[i][j]][j]);
}
inline void swap(int &a,int &b)
{int t=a; a=b; b=t;
}
inline int getmax(int x,int y)
{if (dep[x]<dep[y]) swap(x,y); register int i; int res=0;for (i=P-1;i>=0;--i)if (pa[x][i]&&dep[pa[x][i]]>=dep[y]) res=max(res,f[x][i]),x=pa[x][i];if (x==y) return res;for (i=P-1;i>=0;--i)if (pa[x][i]&&pa[y][i]&&pa[x][i]!=pa[y][i]) {res=max(res,max(f[x][i],f[y][i]));x=pa[x][i]; y=pa[y][i];}return max(res,max(f[x][0],f[y][0]));
}
int main()
{//freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout);register int i; read(n); read(m);memset(e,-1,sizeof(e)); memset(head,-1,sizeof(head));for (i=1;i<=m;++i)read(a[i].l),read(a[i].r),read(a[i].w),read(a[i].col);sort(a+1,a+m+1,comp);for (i=1;i<=n;++i)father[i]=i;for (i=1;i<=m;++i){int fx=getfather(a[i].l),fy=getfather(a[i].r);if (fx!=fy){father[fx]=fy; tot+=a[i].w; a[i].use=1;add(a[i].l,a[i].r,a[i].w); add(a[i].r,a[i].l,a[i].w);}}for (i=1;i<=m;++i)if (a[i].use){if (!c) { c=a[i].col; continue; }if (c!=a[i].col) return printf("%lld",tot),0;}DFS(rt,-1); init(); long long ans=1e18;for (i=1;i<=m;++i)if (!a[i].use&&a[i].col!=c) ans=min(ans,tot-getmax(a[i].l,a[i].r)+a[i].w);return printf("%lld",ans),0;
}

Medium(难度递增)

C. 「QZEZ第一届“饭吉圆”杯程序设计竞赛」路径计数

比较套路的数位DP

我们考虑对题意进行转换,考虑把走过的点写下来,那么一个点的二进制是另一个点的二进制的子集

所以每一个路径上的数肯定是一段1,然后一段0。

就相当于要确定二进制每一位的出现次数,然后出现的二进制位值之和要小于等于\(k\),总和等于\(n\)

仔细想一想,这就是个多重背包了(怎么好像就我一个人写多重背包)

CODE

#include<cstdio>
#include<cctype>
#include<cstring>
using namespace std;
const int N=1e5+5,mod=1e9+9;
int n,k,f[N],x;
inline void inc(int &x,int y)
{if ((x+=y)>=mod) x-=mod;
}
inline void dec(int &x,int y)
{if ((x-=y)<0) x+=mod;
}
int main()
{register int i,j; scanf("%d%d",&k,&n); f[0]=1;for (i=0;(x=1<<i)<=n;++i){for (j=0;j<=n;++j)if (j>=x) inc(f[j],f[j-x]);for (j=n;j>=0;--j)if (j>=(long long)x*(k+1)) dec(f[j],f[j-(long long)x*(k+1)]);}return printf("%d",f[n]),0;
}

K. 「QZEZ第一届“饭吉圆”杯程序设计竞赛」朋友圈

这是典型的技巧题,首先我们想一下这个问题的两种解决方法:

  1. 暴力扫描每一条边,判断两端是否在点集内。复杂度为\(O(qm)\)
  2. 枚举点集中的两个点,然后判断是否存在边 。复杂度为\(O(q\cdot s\ log\ m)\)

然后这两种算法的效率取决于每组数据的点数。我们设一个阈值\(S\):

当点数大于\(S\)时进行算法1,否则进行算法2。

然后我们可以得出取\(S=\frac{q}{log\ m}\)时复杂度达到理论最小值\(O(q\cdot\sqrt{m\ log\ m})\)

CODE

#include<cstdio>
#include<cctype>
#include<cmath>
#include<map>
#include<set>
using namespace std;
const int N=200005;
struct edge
{int x,y;
}e[N];
map <int,bool> vis[N];
int n,m,q,blk,t,ans,num[N];
bool s[N];
inline char tc(void)
{static char fl[100000],*A=fl,*B=fl;return A==B&&(B=(A=fl)+fread(fl,1,100000,stdin),A==B)?EOF:*A++;
}
inline void read(int &x)
{x=0; char ch; while (!isdigit(ch=tc()));while (x=(x<<3)+(x<<1)+ch-'0',isdigit(ch=tc()));
}
inline void write(int x)
{if (x>9) write(x/10);putchar(x%10+'0');
}
inline int solve1(void)
{register int i,ans=0;for (i=1;i<=m;++i)if (s[e[i].x]&&s[e[i].y]) ++ans;return ans;
}
inline int solve2(void)
{register int i,j,ans=0;for (i=1;i<t;++i)for (j=i+1;j<=t;++j)if (vis[num[i]][num[j]]) ++ans;return ans;
}
int main()
{//freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout);register int i; read(n); read(m);for (i=1;i<=m;++i)read(e[i].x),read(e[i].y),vis[e[i].x][e[i].y]=vis[e[i].y][e[i].x]=1; read(q); blk=q/(int)log2(m);while (q--){for (read(t),i=1;i<=t;++i)read(num[i]),s[num[i]]=1;write(t>blk?solve1():solve2()); putchar('\n');for (i=1;i<=t;++i)s[num[i]]=0;}return 0;
}

H. 「QZEZ第一届“饭吉圆”杯程序设计竞赛」字符串匹配2

这道题也是有点骚的,就着法老的std写的,第一次知道双Hash的正确写法

首先读题,我们考虑枚举所有的周期,然后对于每一段我们可以结合特殊最小表示法+双Hash来\(O(1)\)求

然后这里我们要知道一个调和级数公式(其实我是知道的,也和另外一个初二口头AC了这道题,不过最后时间不够了,而且我们也不敢上):

\(n+\frac{n}{2}+\frac{n}{3}+\frac{n}{4}+\cdots+\frac{n}{n-1}+1=n\ In\ n\)

然后把每种字符出现的位置用01二进制串表示,然后hash,判断是否能两两对应就可以了 。

CODE

#include<cstdio>
#include<cstring>
#include<vector>
#include<algorithm>
#define fir first
#define sec second
using namespace std;
typedef pair<int,int> Hash;
const int N=1e5+5;
const Hash seed={233,2333},mod={1e9+7,1e9+9};
vector <Hash> a,b;
char s[N];
int len;
Hash pre[5][N],pw[N];
Hash operator %(Hash a,Hash b) { return Hash((a.fir+b.fir)%b.fir,(a.sec+b.sec)%b.sec); }
Hash operator +(Hash a,Hash b) { return Hash(a.fir+b.fir,a.sec+b.sec)%mod; }
Hash operator -(Hash a,Hash b) { return Hash(a.fir-b.fir,a.sec-b.sec)%mod; }
Hash operator *(Hash a,Hash b) { return Hash(1LL*a.fir*b.fir%mod.fir,1LL*a.sec*b.sec%mod.sec); }
inline void write(int x)
{if (x>9) write(x/10);putchar(x%10+'0');
}
inline int min(int a,int b)
{return a<b?a:b;
}
inline Hash get_sub(int k,int l,int r)
{return pre[k][r]-(pre[k][l-1]*pw[r-l+1]);
}
int main()
{register int i,j,k; scanf("%s",s+1); len=strlen(s+1);for (pw[0]={1,1},i=1;i<=len;++i)pw[i]=pw[i-1]*seed;for(i=1;i<=len;++i){for(j=0;j<5;++j) pre[j][i]=pre[j][i-1]*seed;pre[s[i]-'a'][i]=pre[s[i]-'a'][i]+Hash(1,1);}for (i=1;i<=len;++i){bool flag=1;for (j=i+1;j<=len;j+=i){a.clear(); b.clear();for (k=0;k<5;++k)a.push_back(get_sub(k,1,min(i,len-j+1))),b.push_back(get_sub(k,j,min(i+j-1,len)));sort(a.begin(),a.end()); sort(b.begin(),b.end());if (a!=b) { flag=0; break; }}if (flag) write(i),putchar(' ');}return 0;
}

E. 「QZEZ第一届“饭吉圆”杯程序设计竞赛」暑假作业

首先先发现对\(t\)从小到大排序后可以得到最优解(这个很好证明而且也很显然,实在不行结合样例理解一下即可)。

考虑排序后如何算出初始的最优解,我们可以分析后得出答案等价于

\(\sum_{i=1}^n l_i-t_i\cdot(n-i+1)\)

然后我们考虑修改,其实就是取走一个数在放上一个数的过程,我们发现只要得出这个点(老的)对答案的贡献和新的点对答案的贡献。

很显然,一个点被删除/加入对于它的排名有影响,对排在它后面的数的答案也有影响。

因此我们分别考虑这两个影响,排名可以用类似于求逆序对的方法用树状数组求知。

然后考虑对于排在它后面的数统统前移一位,其实也是一个求和(\(\sum t_i\))的过程,因此我们再开一维树状数组来直接统计即可。

具体实现看CODE

#include<cstdio>
#include<cctype>
#include<algorithm>
using namespace std;
typedef long long LL;
const LL N=2e5+5;
LL n,m,l[N],t[N],r[N],x,nl,nt,ans,tree[2][N>>1];
inline char tc(void)
{static char fl[100000],*A=fl,*B=fl;return A==B&&(B=(A=fl)+fread(fl,1,100000,stdin),A==B)?EOF:*A++;
}
inline void read(LL &x)
{x=0; char ch; while (!isdigit(ch=tc()));while (x=(x<<3)+(x<<1)+ch-'0',isdigit(ch=tc()));
}
inline void write(LL x)
{if (x<0) putchar('-'),x=-x;if (x>9) write(x/10); putchar(x%10+'0');
}
inline void add(LL x,LL y,LL z)
{for (;x<=1e5;tree[z][x]+=y,x+=x&-x);
}
inline LL get(LL x,LL y)
{LL tot=0; for (;x;tot+=tree[y][x],x-=x&-x); return tot;
}
int main()
{//freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout);register LL i; read(n); read(m);for (i=1;i<=n;++i)read(l[i]),read(t[i]),r[i]=t[i],ans+=l[i];sort(r+1,r+n+1);for (i=1;i<=n;++i)ans-=r[i]*(n-i+1),add(r[i],1,0),add(r[i],r[i],1);write(ans); putchar('\n');while (m--){read(x); read(nl); read(nt);ans-=l[x]; l[x]=nl; ans+=l[x];add(t[x],-1,0); add(t[x],-t[x],1); ans+=t[x]*(n-get(t[x],0))+get(t[x],1);t[x]=nt; ans-=t[x]*(n-get(t[x],0))+get(t[x],1); add(t[x],1,0); add(t[x],t[x],1);write(ans); putchar('\n');}return 0;
}

转载于:https://www.cnblogs.com/cjjsb/p/9255601.html

QZEZ第一届“饭吉圆”杯程序设计竞赛相关推荐

  1. E-捡贝壳 2021年广东工业大学第十五届文远知行杯程序设计竞赛(同步赛)

    E-捡贝壳 2021年广东工业大学第十五届文远知行杯程序设计竞赛(同步赛) 小明来到一片海滩上,他很喜欢捡贝壳,但他只喜欢质量为x的倍数的贝壳. 贝壳被排列成一条直线,下标从1到n编号,小明打算从编号 ...

  2. G-分割 2021年广东工业大学第十五届文远知行杯程序设计竞赛(同步赛)

    G-分割 2021年广东工业大学第十五届文远知行杯程序设计竞赛(同步赛) 在一个二维平面, 有n条平行于y轴的直线, 他们的x坐标是x[i], m条平行于x轴的直线y[i],他们的y坐标是y[i]. ...

  3. 2021年广东工业大学第十五届文远知行杯程序设计竞赛(同步赛)C题 图墙+拉格朗日四平方数和定理

    题意: 其实就是问一个数字能不能表示成5个正平方数的和. 题目: 链接:https://ac.nowcoder.com/acm/problem/220347 来源:牛客网 时间限制:C/C++ 1秒, ...

  4. 2021年广东工业大学第十五届文远知行杯程序设计竞赛(同步赛)E.捡贝壳

    题目链接 题目描述 小明来到一片海滩上,他很喜欢捡贝壳,但他只喜欢质量为x的倍数的贝壳. 贝壳被排列成一条直线,下标从 111 到 nnn 编号,小明打算从编号为区间 [l,r]\left [l,r ...

  5. 2021年广东工业大学第十五届文远知行杯程序设计竞赛(同步赛) 部分题解

    先声明,这场我爆0了一题都没做出来. B题 链接:https://ac.nowcoder.com/acm/contest/13504/B 来源:牛客网 题目描述 母牛哥在电脑面前坐久了,想站起来看看窗 ...

  6. 2021年广东工业大学第十五届文远知行杯程序设计竞赛(同步赛)B.找山坡

    题目链接 题目描述 母牛哥在电脑面前坐久了,想站起来看看窗外的小山坡,于是就想出了这个问题: 给定一个大小为 n 的数组 a,序号从 1 开始, 计算: max{ R - L | 1 <= L ...

  7. 2021年广东工业大学第十五届文远知行杯程序设计竞赛(同步赛)

    A题M型字符串 链接:https://ac.nowcoder.com/acm/contest/13504/A 来源:牛客网 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 262144 ...

  8. 2021年广东工业大学第十五届文远知行杯程序设计竞赛(同步赛)详解

    传送门 A M形字符 题意: M形字符串指的是由两个相同的回文串拼接而成 给你一个串S,问有多少个前缀是M形字符串 思路: M形是有两个相同的回文串构成的,所以这个M形串本身就是回文串,我们只需要判断 ...

  9. 2021年广东工业大学第十五届文远知行杯程序设计竞赛(同步赛) H.有多短 思维

    传送门 文章目录 题意: 思路: 题意: 思路: 可以发现树的直径起点和终点一定是两个度数为111的点,所以我们可以把kkk平均的分给所有度数为111的点,这样答案就为2∗kcnt\frac{2*k} ...

最新文章

  1. kdd cup 2019
  2. SQL Azure(十) SQL Azure Data Sync数据同步功能(上)
  3. 从HTTP 400 bad request说起 - 一个函数被注释掉后引起的血案
  4. SpringCloud个人笔记-02-Feign初体验
  5. 入门干货之Grpc的.Net 封装-MagicOnion
  6. 全球100款大数据工具汇总(前50款)
  7. 华为荣耀20计算机,华为云电脑将停止服务/荣耀新机保护壳曝光/小米新机渲染图曝光...
  8. 纯CSS实现React Logo图形,内含详细解析
  9. 为什么我不看好PWA
  10. 《大数据导论》一1.4 案例学习背景
  11. 做数据分析的目的是什么
  12. ansible+packer+terraform在aws上布署web服务器
  13. Mysql SQLyog 使用详解
  14. C Library User 手册(25)
  15. 轻松盘,资产盘点不再难 RFID办公资产盘点管理
  16. 3月9日火箭vs黄蜂
  17. 有效沟通bic法则_有效沟通bic法则_合格职场人都会的3个有效的沟通法则
  18. lucene 学习笔记之飞龙在天
  19. jQuery怎么读,应该这样读不要读错了
  20. 一大波苹果CMS系统主题来袭

热门文章

  1. java map clone_Java中HashMap的clone()方法: java.util.HashMap.clone() - Break易站
  2. matlab main函数_Python 和MATLAB 制作Gif 图像
  3. 计算机原理及应用课程,课程介绍
  4. php如何导入数据,““php中如何将execl的数据导入到数据库中
  5. 力扣151. 翻转字符串里的单词
  6. Linux网络故障排查命令(ifconfig、ping、telnet、netstat、lsof、nc、curl、tcpdump)
  7. 《MySQL——group by使用tips》
  8. Java Throwable setStackTrace()方法与示例
  9. java类名与文件名_为什么Java文件名必须与公共类名相同?
  10. Python中的a+=a和a=a+a的区别(认真看完后,我相信你一定会回来感谢我的)