首页 > 其他分享 >Solution - Atcoder AGC028B Removing Blocks

Solution - Atcoder AGC028B Removing Blocks

时间:2024-07-30 14:40:15浏览次数:13  
标签:AGC028B Atcoder pre frac int ll maxn Blocks operatorname

因为贡献的方法是相加,一种想法就是拆开,对每一项单独贡献。

不难发现这题目中的贡献其实只涉及到两点之间。
即删除 \(x\) 时 \(y\) 也产生了贡献。

考虑这个贡献会在多少种排列中出现。
令 \(d = |x - y| + 1\),即 \(x, y\) 中的点数。
能发现排列需要满足除 \(x\) 外的 \(d - 1\) 个点都必须出现在 \(x\) 之后,不然 \(x, y\) 就不连通了。

考虑用插板法的想法来计数。
即对于第 \(i + 1\) 次插入,此时有 \(i\) 个元素,\(i + 1\) 个空位可以插。
考虑先插入除 \(x\) 的 \(d - 1\) 个位置,方案数就为 \((d - 1)!\)。
接下来考虑插入 \(x\),因为 \(x\) 必须在这些位置前面出现,所以对于 \(x\) 方案数就为 \(1\)。
对于之后的 \(n - d\) 个位置,也没有任何限制,方案数为 \(\frac{n!}{d!}\)。
于是方案数就为 \((d - 1)!\times \frac{n}{d!} = \frac{n!}{d}\)。

于是现在相当于就是对于每一个 \(y\) 求 \(\sum\limits_{x = 1}^n \frac{n!}{|x - y| + 1}\)。
考虑令 \(\operatorname{pre}_i = \sum\limits_{j = 1}^n \frac{n!}{d}\)。
对于这个绝对值,考虑拆成 \(x\le y\) 和 \(x\ge y\) 两部分,再减去 \(x = y\)。
于是可以化为 \(\operatorname{pre}_i + \operatorname{pre}_{n - i + 1} - \operatorname{pre}_1\)。

时间复杂度 \(\mathcal{O}(n)\)。

#include<bits/stdc++.h>
using ll = long long;
constexpr ll mod = 1e9 + 7;
const int maxn = 1e5 + 10;
ll inv[maxn], f[maxn], pre[maxn];
int main() {
   int n; scanf("%d", &n);
   ll fac = 1;
   for (int i = 1; i <= n; i++)
      (fac *= i) %= mod;
   inv[0] = inv[1] = 1;
   for (int i = 2; i <= n; i++)
      inv[i] = inv[mod % i] * (mod - mod / i) % mod;
   for (int i = 1; i <= n; i++)
      f[i] = fac * inv[i] % mod;
   for (int i = 1; i <= n; i++)
      pre[i] = (pre[i - 1] + f[i]) % mod;
   ll ans = 0;
   for (int i = 1, x; i <= n; i++)
      scanf("%d", &x), (ans += (pre[i] + pre[n - i + 1] - pre[1] + mod) * x) %= mod;
   printf("%lld\n", ans);
   return 0;
}

标签:AGC028B,Atcoder,pre,frac,int,ll,maxn,Blocks,operatorname
From: https://www.cnblogs.com/rizynvu/p/18332327

相关文章

  • Atcoder ABC364 D-F
    AtcoderABC364D-FD-K-thNearest链接:D-K-thNearest(atcoder.jp)简要题意:问题陈述在一条数线上有\(N+Q\)个点\(A_1,\dots,A_N,B_1,\dots,B_Q\),其中点\(A_i\)的坐标为\(a_i\),点\(B_j\)的坐标为\(b_j\)。请就每个点\(j=1,2,\dots,Q\)回答下面的问题:......
  • Solution - Atcoder YPC2019E Odd Subrectangles
    首先对于\(0/1\)和为奇数,转化为异或为\(1\)来考虑。考虑如果已经确定了行的选取,又该如何计数。考虑对于每一列,都处理好在对应行的位置的异或值。然后记\(\operatorname{c}_0,\operatorname{c}_1\)表示列异或值为\(0/1\)的数量。知道了\(\operatorname{c}_0,\op......
  • Solution - Atcoder UTPC2023P Priority Queue 3
    考虑找一些关于合法的\(X\)加入的数的判定条件。假设遇到了一个\(\operatorname{pop}\)操作,令这里删除的数为\(a_i\),显然\(X\)中的数应该要有\(a_i\),其次\(X\)中其他的加入的数要么\(>a_i\)要么是\(a\)中的元素(在前面的\(\operatorname{pop}\)就已经被删了)。于......
  • AtCoder Beginner Contest 362
    AtCoderBeginnerContest362前言vp的时候出了四题,被C题卡了一会,很久才出,D题是dijkstra的板子,改下条件即可,E题是个计数dp,这类题一直不怎么擅长,想起之前杭电第一场那个序列立方的题也是类似这种计数dp,需要加强练习。A-BuyaPen(atcoder.jp)思路判断两两最小。......
  • Solution - Atcoder ABC280Ex Substring Sort
    对于这种子串问题,且有多个基础串,一个比较直观的想法就是先上个广义SAM。考虑SAM与字典序如何联系上。因为跳\(\operatorname{fail}\)相当于是删除子串的一个前缀,直接这样子明显是不行的,因为跳了\(\operatorname{fail}\)字典序没有一个很直观地表示。但是反过来考虑反串,......
  • Solution - Atcoder ARC114F Permutation Division
    令\(a\)为题目中的\(P\)。首先考虑后手的重排策略是什么。因为\(a\)是个排列,元素互不相同,那么肯定就是按照每一段的第一个数的大小,越大的放在越前面。那么当\(a_1\lek\)的时候,显然先手会把以\(1\simk\)开头来划分段。因为否则存在一个开头\(>k\)的段,后手把其放......
  • AtCoder Beginner Contest 363 题解 A-D(待补充)
    A-PilingUp1.1思路其实就是向上取百位的整,需要增加多少,123则为200-123=177;1.2代码voidsolve(){intn;cin>>n;intt=n/100;cout<<(t+1)*100-n;}B-JapaneseCursedDoll 2.1思路就是判断最少需要多少天,会有大于等于P个人......
  • AtCoder Beginner Contest 363
    比赛地址添加链接描述A-PilingUp算法:模拟题目大意在AtCoder竞赛平台中,用户的等级通过正整数分数表示,并根据分数显示相应数量的^符号。分数与^符号显示的规则如下:当分数在1到99(包括99)之间时,显示一个^。当分数在100到199(包括199)之间时,显示两个^。......
  • AtCoder Beginner Contest 364 补题记录(A~F)
    VP五十八分钟苏童流体。好耶A#defineGLIBCXX_DEBUG#include<iostream>#include<cstring>#include<cstdio>#defineintlonglongconstintN=500100;std::strings[N];signedmain(){intn,cnt=1;scanf("%lld",&n);f......
  • AtCoder Beginner Contest 364
    A-GluttonTakahashi(abc364A)题目大意给定\(n\)个字符串,问是否有两个相邻的sweet。解题思路遍历判断当前字符串与上一个字符串是否都为sweet即可。神奇的代码#include<bits/stdc++.h>usingnamespacestd;usingLL=longlong;intmain(void){ios::sync_......