卡 B 下大分了。

A. Toasts for Breakfast Party

发现题意是让方差尽可能小,就是让 \(A\) 里的值尽可能接近。

所以从小到大排个序,把 \(A_{N,\dots,N-M+1}\) 依次放进 \(1,2,\dots,M\),再把 \(A_{N-M,\dots,1}\) 依次放进 \(M,M-1,\dots,2M-N+1\) 就赢了。


B. Product of Divisors

大家快看,这里有一个试图在质因数分解后的指数上推点式子,于是卡 B 1h 的樱雪喵 /cf

Description

给定 \(A,B\),问 \(A^B\) 所有因数的积不断除以 \(A\),最多能除几次。

\(A\le 10^{12},B\le 10^{18}\)。

Solution

发现因数是成对的,对每个因数都有 \(x\times \frac{A^B}{x}=A^B\),设 \(A^B\) 的因数个数为 \(n\)。

如果 \(n\) 是偶数,把因数两两分成 \(\frac{n}{2}\) 对,每对的积都是 \(A^B\),\(A^B\) 的因数之积就是 \(A^{(Bn/2)}\),答案是 \(\frac{Bn}{2}\)。

如果是奇数,说明 \(A^B\) 是完全平方数,我们把这个数单独拆出来考虑,\(A^B\) 的因数之积是 \(A^{B(n-1)/2}\times \sqrt{A^B}\),答案也是这个。

注意完全平方数分为 \(A\) 本身是完全平方数和 \(B\) 是偶数两种情况。

于是就做完了,时间复杂度瓶颈在质因数分解,\(O(\sqrt{A})\)。

Code
bool flag=0;
signed main()
{
A=read(),B=read();
if((int)sqrt((long long)A)*(int)sqrt((long long)A)==A) flag=1;
for(int i=2;i*i<=A;i++)
{
if(A%i==0)
{
a[++cnt]=i;
while(A%i==0) b[cnt]++,A/=i;
}
}
if(A>1) b[++cnt]=1;
int res=1;
for(int i=1;i<=cnt;i++) res=res*(b[i]*B%mod+1)%mod;
if(B%2==0||flag) res=(res+mod-1)%mod;
res=res*qpow(2,mod-2)%mod*B%mod;
if(B%2==0||flag) res=(res+B/2)%mod;
cout<<(long long)res<<endl;
return 0;
}

C. MST on Line++

完全不会做,人菜,没救了。

Description

给定正整数 \(n,K\) 和一个长度为 \(n\) 的序列 \(A\)。对于一个 \(1\sim n\) 的排列 \(P\),我们定义 \(f(P)\) 为以下问题的答案:

给一个 \(n\) 个点的无向带权图,对于两点 \(i<j\),当且仅当 \(j-i\le K\) 时,它们之间有边,边权为 \(\max(A_{P_i},A_{P_j})\)。

求这个图的最小生成树边权和。

对于所有可能的排列 \(P\),求出它们的 \(f(P)\) 之和,答案对 \(998\,244\,353\) 取模。

\(1\le K< N\le 5000\),\(1\le A_i \le 10^9\)。

Solution

发现我们只要求出每条边被选了几次,就可以统计出它们的权值和。

考虑 Kruskal 求最小生成树的过程,发现按边权排序后,我们会选择哪些边只与边之间的大小关系有关,与具体的边权无关。那么我们把 \(A_i\) 升序排序后,令第 \(i\) 类边表示边权为 \(A_i\) 的边,就可以只关心每类边分别选了几次。

考虑如下的子问题:

给定一个边权的限制 \(a\) 和一个排列 \(P\),对于 \(i<j\),\(i,j\) 之间有无权边当且仅当 \(j-i\le K\) 且 \(\max(P_i,P_j)\le a\)。求在边之间不形成环的条件下最多选择几条边。

对于一个排列 \(P\),边权为 \(A_i\) 的边被选择的条数就是 \(a=i\) 时的答案减掉 \(a=i-1\) 时的答案。

设 \(f_{i}\) 表示所有排列 \(P\) 在 \(a=i\) 时该子问题的答案之和。那么有:

\[ans=\sum_{i=2}^{n} A_i(f_i-f_{i-1})
\]

考虑 \(f_i\) 怎么求。

对于一个排列 \(P\),我们令所有 \(P_j\le i\) 的下标 \(j\) 构成集合 \(Q\),\(Q\) 中的元素升序排序。因为边权是取 \(\max\),不在 \(Q\) 内的点一定没有任何连边。

故所有 \(Q_j-Q_{j-1}\le K\) 的下标之间都有连边,且把它们都选上一定是不劣的。对于一个排列 \(P\) 的答案就是 \(\sum\limits_{j=2}^i [Q_j-Q_{j-1}\le K]\)。

枚举一个 \(j\),对于所有排列计算满足 \(Q_j-Q_{j-1}\le K\) 的数量。\(Q_j-Q_{j-1}=k\) 的排列有 \(\binom{n-k}{i-1}\) 个,\(\le K\) 的就有 \(\sum\limits_{j=1}^K \binom{n-j}{i-l}\) 个。那么一共有 \(i-1\) 对相邻的下标,一个 \(Q\) 序列对答案的贡献是 \((i-1)\sum\limits_{j=1}^K\binom{n-j}{i-l}\)。

一个 \(Q\) 序列对应的排列 \(P\) 的个数是 \(i!(n-i)!\),最终的式子是

\[f_i=i!(n-i)!(i-1)\sum_{j=1}^K \binom{n-j}{i-1}
\]

求 \(f_i\) 的时间复杂度为 \(O(nK)\),求答案的时间复杂度为 \(O(n)\)。

Code
#define int long long
const int N=5005,mod=998244353;
int n,K,a[N];
int f[N],jc[N],c[N][N];
il void init(int mx)
{
for(int i=0;i<=mx;i++)
for(int j=0;j<=i;j++) c[i][j]=j?(c[i-1][j-1]+c[i-1][j])%mod:1;
}
signed main()
{
n=read(),K=read(); init(n);
for(int i=1;i<=n;i++) a[i]=read(); sort(a+1,a+n+1);
jc[0]=1;
for(int i=1;i<=n;i++) jc[i]=jc[i-1]*i%mod;
for(int i=1;i<=n;i++)
for(int j=1;j<=K;j++) f[i]=(f[i]+jc[i]*jc[n-i]%mod*(i-1)%mod*c[n-j][i-1]%mod)%mod;
// for(int i=1;i<=n;i++) cout<<"f "<<i<<" "<<f[i]<<endl;
int ans=0;
for(int i=1;i<=n;i++) ans=(ans+a[i]*(f[i]+mod-f[i-1])%mod)%mod;
printf("%lld\n",ans);
return 0;
}

D. Good Permutation

Description

对于一个 \((1,2,\dots,N)\) 的排列 \(Q\),称其是好的,当且仅当

  • 对于每个整数 \(i \in [1,N]\),在若干次 \(i \gets Q_i\) 后能够得到 \(i=1\)。

给定一个排列 \(P\),每次操作可以交换两个数。使用最小的操作次数,使得 \(P\) 成为一个好的排列,若有多种解,输出字典序最小的。

Solution

怎么连着两场 D<C 呢?

对于每个 \(i\),我们连边 \(i\to P_i\),那么这张图形成了若干个不相交的环。\(P\) 是一个好的排列当且仅当图上只有一个环。

从小到大依次贪心确定每一位的值,设当前位为 \(i\):

  • 如果存在至少一个 \(P_j=u,j>i\),满足 \(i,j\) 不在一个环且 \(u<P_i\),我们找到最小的 \(u\),并 \(\text{swap}(P_i,P_j)\)。
  • 否则我们不希望字典序变大,尽量不换。但如果 \(i\) 是它所在连通块的最后一个位置,必须要换,找到后面最小的 \(u\),设 \(P_j=u\),并 \(\text{swap}(P_i,P_j)\)。

判断是否在一个环使用并查集,用一个 set 维护每个连通块之间的大小关系。

Code
const int N=2e5+5;
#define pii pair<int,int>
#define fi first
#define se second
int n,a[N];
int fa[N],mn[N],siz[N],pos[N];
set<pii> s;
int find(int x) {return fa[x]==x?x:fa[x]=find(fa[x]);}
void merge(int x,int y)
{
x=find(x),y=find(y); if(x==y) return;
s.erase(pii(mn[x],x)),s.erase(pii(mn[y],y));
fa[x]=y,siz[y]+=siz[x],mn[y]=min(mn[y],mn[x]);
s.insert(pii(mn[y],y));
}
int main()
{
int T=read();
while(T--)
{
s.clear();
n=read();
for(int i=1;i<=n;i++) a[i]=read(),pos[a[i]]=i;
for(int i=1;i<=n;i++) fa[i]=i,siz[i]=1,mn[i]=i,s.insert(pii(i,i));
for(int i=1;i<=n;i++) merge(i,a[i]);
for(int i=1;i<=n;i++)
{
if(s.size()==1) break;
auto it=s.begin();
while(find(it->se)==find(i)) it++;
int u=it->fi;
if(u<a[i]||siz[find(i)]==1)
{
int j=pos[u]; swap(a[i],a[j]),swap(pos[a[i]],pos[a[j]]);
merge(i,j);
}
siz[find(i)]--;
}
for(int i=1;i<=n;i++) printf("%d ",a[i]);
printf("\n");
}
return 0;
}

E. One Square in a Triangle

Description

多组询问,每次给定一个数 \(S\),要求构造一个符合如下条件的三角形:

  • 三角形的顶点都在格点上;
  • 面积为 \(\frac{S}{2}\);
  • 恰好包含了一个顶点在格点上的 \(1\times 1\) 的正方形(换句话说,恰好包含一个完整的格子)

\(T\le 10^5,S\le 10^8\)。

Solution

做法参考部分题解,画了几个图。

设三角形的三个顶点分别为 \(a,b,c\)。整体平移这个三角形不影响答案,所以钦定 \(a=(0,0)\) 以简化计算。

首先 \(S\) 为偶数的情况,我们可以钦定三角形的底为 \(2\),令 \(a=(0,0),b=(2,0),c=(\frac{S}{2},\frac{S}{2})\)。

这在 \(S\ge 4\) 的情况下可以看出是对的,而手玩可以发现 \(S=2\) 无解。

考虑 \(S\) 为奇数的情况。类比偶数时答案的形态:我们确定一条底边,并让剩下的一个点在某条直线上移动。

设 \(b=(x_b,y_b),c=(x_c,y_c)\),根据三角形的面积公式(可以根据叉积的几何意义证),有

\[S=|x_b y_c - x_c y_b|
\]

\(S\) 是奇数,则 \(x_b y_c\) 与 \(x_c y_b\) 有一个是奇数,即要么 \(x_b,y_c\) 都是奇数,要么 \(x_c,y_b\) 都是奇数。令 \(b=(3,1)\)。

那么式子变成了 \(S=|3y_c - x_c|\)。

要令 \(3y_c\) 和 \(x_c\) 的奇偶性始终不同,考虑钦定 \(y_c=x_c+1\)。答案即为 \(a=(0,0),b=(3,1),c=(\frac{S-3}{2},\frac{S-1}{2})\)。



如图,在 $S\ge 9 $ 时满足条件。

手玩小于 \(9\) 的情况,发现 \(S=1,3,5,7\) 均无解。

int T,S;
int main()
{
T=read();
while(T--)
{
S=read();
if(S<9&&(S&1)||S==2) {printf("No\n");continue;}
printf("Yes\n");
if(S&1) printf("0 0 3 1 %d %d\n",(S-3)/2,(S-1)/2);
else printf("0 0 2 0 %d %d\n",S/2,S/2);
}
return 0;
}

F. Tree Tree Tree

不会。

Atcoder Regular Contest 167的更多相关文章

  1. AtCoder Regular Contest 061

    AtCoder Regular Contest 061 C.Many Formulas 题意 给长度不超过\(10\)且由\(0\)到\(9\)数字组成的串S. 可以在两数字间放\(+\)号. 求所有 ...

  2. AtCoder Regular Contest 094 (ARC094) CDE题解

    原文链接http://www.cnblogs.com/zhouzhendong/p/8735114.html $AtCoder\ Regular\ Contest\ 094(ARC094)\ CDE$ ...

  3. AtCoder Regular Contest 092

    AtCoder Regular Contest 092 C - 2D Plane 2N Points 题意: 二维平面上给了\(2N\)个点,其中\(N\)个是\(A\)类点,\(N\)个是\(B\) ...

  4. AtCoder Regular Contest 093

    AtCoder Regular Contest 093 C - Traveling Plan 题意: 给定n个点,求出删去i号点时,按顺序从起点到一号点走到n号点最后回到起点所走的路程是多少. \(n ...

  5. AtCoder Regular Contest 094

    AtCoder Regular Contest 094 C - Same Integers 题意: 给定\(a,b,c\)三个数,可以进行两个操作:1.把一个数+2:2.把任意两个数+1.求最少需要几 ...

  6. AtCoder Regular Contest 095

    AtCoder Regular Contest 095 C - Many Medians 题意: 给出n个数,求出去掉第i个数之后所有数的中位数,保证n是偶数. \(n\le 200000\) 分析: ...

  7. AtCoder Regular Contest 102

    AtCoder Regular Contest 102 C - Triangular Relationship 题意: 给出n,k求有多少个不大于n的三元组,使其中两两数字的和都是k的倍数,数字可以重 ...

  8. AtCoder Regular Contest 096

    AtCoder Regular Contest 096 C - Many Medians 题意: 有A,B两种匹萨和三种购买方案,买一个A,买一个B,买半个A和半个B,花费分别为a,b,c. 求买X个 ...

  9. AtCoder Regular Contest 097

    AtCoder Regular Contest 097 C - K-th Substring 题意: 求一个长度小于等于5000的字符串的第K小子串,相同子串算一个. K<=5. 分析: 一眼看 ...

  10. AtCoder Regular Contest 098

    AtCoder Regular Contest 098 C - Attention 题意 给定一个只包含"E","W"字符串,可以花一的花费使他们互相转换.选定 ...

随机推荐

  1. React中编写操作树形数据的自定义Hook

    什么是 Hook hook 即为钩子,是一种特殊的函数,它可以让你在函数式组件中使用一些 react 特性,目前在 react 中常用的 hook 有以下几类 useState: 用于在函数组件中定义 ...

  2. 【VUE】 文件预览

    [VUE] 文件预览 上传前预览 word文档:docx.doc 核心代码 import {renderAsync} from "docx-preview"; /** * 渲染do ...

  3. 使用Stable Diffusion制作AI数字人视频的简明教程

    基本方法 搞一张照片,搞一段语音,合成照片和语音,同时让照片中的人物动起来,特别是头.眼睛和嘴. 语音合成 语音合成的方法很多,也比较成熟了,大家可以选择自己方便的,直接录音也可以,只要能生成一个语音 ...

  4. 《敏捷无敌之DevOps时代》读后感

    背景: 2020年基于我司业务形态,我开始实行敏捷项目管理.以敏捷为道,Scrum为法,迭代为术,禅道作器,大张旗鼓的搞了2年敏捷开发.随着时间推移,问题出现在2022年,当时我们已经完全按照Scru ...

  5. 2023-07-31:用r、e、d三种字符,拼出一个回文子串数量等于x的字符串。 1 <= x <= 10^5。 来自百度。

    2023-07-31:用r.e.d三种字符,拼出一个回文子串数量等于x的字符串. 1 <= x <= 10^5. 来自百度. 答案2023-07-31: 大体步骤如下: 1.初始化一个字符 ...

  6. ASP.NET WebForm中asp:Repeater和UI:Grid数据为空时如何显示表头?

    一.asp:Repeater Repeater 控件用于显示被绑定在该控件上的项目的重复列表.Repeater 控件可被绑定到数据库表.XML 文件或者其他项目列表. 1.1-前台页面代码 <a ...

  7. 常用c++ STL 汇总

    常用STL: vector 变长数组,倍增的思想 初始化: //初始化 vector<int> a; vector<int> a(n); vector<int> a ...

  8. 揭秘 .NET 中的 TimerQueue(下)

    前言 上文给大家介绍了 TimerQueue 的任务调度算法. https://www.cnblogs.com/eventhorizon/p/17557821.html 这边做一个简单的复习. Tim ...

  9. nginx配置gzip压缩

    前言 为提高用户获取响应数据的速度,Nginx服务器可以将响应数据进行gzip压缩,在减小响应数据的大小后再发送给用户端浏览器. 要想启用gzip压缩,需要浏览器支持gzip压缩功能,目前大多数浏览器 ...

  10. 文盘Rust -- Mutex解决并发写文件乱序问题

    在实际开发过程中,我们可能会遇到并发写文件的场景,如果处理不当很可能出现文件内容乱序问题.下面我们通过一个示例程序描述这一过程并给出解决该问题的方法. use std::{ fs::{self, Fi ...