• 【题解】P6042 「ACOI2020」学园祭


    link

    题意


    ∑ i = 1 n ∑ j = 1 i ∑ k = 1 j gcd ⁡ ( ( i − j ) ! , ( j − k ) ! ) \sum\limits_{i=1}^{n}\sum\limits_{j=1}^{i}\sum\limits_{k=1}^{j}\gcd((i-j)!,(j-k)!) i=1nj=1ik=1jgcd((ij)!,(jk)!)
    T T T 组数据。 T , n ≤ 1 0 6 T,n\le 10^6 T,n106

    题解

    易得
    a n s = ∑ i = 1 n ∑ j = 1 i ∑ k = 1 j min ⁡ ( i − j , j − k ) ! ans =\sum\limits_{i=1}^{n}\sum\limits_{j=1}^{i}\sum\limits_{k=1}^{j}\min(i-j,j-k)! ans=i=1nj=1ik=1jmin(ij,jk)!
    x = i − j , y = j − k x=i-j,y=j-k x=ij,y=jk。显然 x , y ≥ 0 , x + y = i − k ≤ n − 1 x,y\ge 0,x+y=i-k\le n-1 x,y0,x+y=ikn1

    那么 0 ≤ min ⁡ ( x , y ) ≤ ⌊ n − 1 2 ⌋ 0\le \min(x,y)\le \lfloor\frac{n-1}{2}\rfloor 0min(x,y)2n1

    考虑枚举 d = min ⁡ ( x , y ) d=\min(x,y) d=min(x,y),计算对于每个 d d d 有多少种 i , j , k i,j,k i,j,k 的取值方案 c n t d cnt_d cntd
    a n s = ∑ d = 0 ⌊ n − 1 2 ⌋ d ! ⋅ c n t d ans=\sum\limits_{d=0}^{\lfloor\frac{n-1}{2}\rfloor}d!\cdot cnt_d ans=d=02n1d!cntd
    对于一组确定的 x , y x,y x,y,若我们能确定 k k k 的值,那么有 j = y + k , i = x + j = x + y + k j=y+k,i=x+j=x+y+k j=y+k,i=x+j=x+y+k,也就是确定一个 k k k 即可确定一组 i , j , k i,j,k i,j,k。因为 i ≤ n i\le n in,所以 x + y + k ≤ n x+y+k\le n x+y+kn,所以 k ≤ n − x − y k\le n-x-y knxy。即对于一组确定的 x , y x,y x,y,有 n − x − y n-x-y nxy i , j , k i,j,k i,j,k 与之对应。

    考虑对于确定的 d d d,有多少组 x , y x,y x,y。不妨假设 x = d x=d x=d,则 y y y 显然满足 y ≥ d y\ge d yd,因为 x + y ≤ n − 1 x+y\le n-1 x+yn1,所以 d ≤ y ≤ n − x − 1 d\le y\le n-x-1 dynx1,所以 y y y n − x − 1 − d + 1 = n − x − d = n − 2 d n-x-1-d+1=n-x-d=n-2d nx1d+1=nxd=n2d 种取值。那么对于所有的 d d d,当 x = d x=d x=d 时总共的方案为 ∑ d n − 2 d = ( n − 2 d + 1 ) ( n − 2 d ) 2 \sum\limits_{d} n-2d=\dfrac{(n-2d+1)(n-2d)}{2} dn2d=2(n2d+1)(n2d) x x x d d d y y y d d d 的方案是一样的,所以直接乘 2 2 2。注意这里对于 x = y = d x=y=d x=y=d 的方案算了两次,减去 n − 2 d n-2d n2d 即可。

    现在有
    c n t d = 2 ⋅ ( n − 2 d + 1 ) ( n − 2 d ) 2 − ( n − 2 d ) = ( n − 2 d ) 2 cnt_d=2\cdot\dfrac{(n-2d+1)(n-2d)}{2}-(n-2d)=(n-2d)^2 cntd=22(n2d+1)(n2d)(n2d)=(n2d)2
    所以现在有
    a n s = ∑ d = 0 ⌊ n − 1 2 ⌋ d ! ⋅ ( n − 2 d ) 2 ans=\sum\limits_{d=0}^{\lfloor\frac{n-1}{2}\rfloor}d!\cdot (n-2d)^2 ans=d=02n1d!(n2d)2
    看起来现在可以 O ( T n ) O(Tn) O(Tn) 解决这个问题了。

    只需要再进一步推导:
    a n s = ∑ d = 0 ⌊ n − 1 2 ⌋ ( n 2 d ! − d ! 4 n d + d ! 4 d 2 ) = n 2 ∑ d = 0 ⌊ n − 1 2 ⌋ d ! − 4 n ∑ d = 0 ⌊ n − 1 2 ⌋ d ! ⋅ d + 4 ∑ d = 0 ⌊ n − 1 2 ⌋ d ! ⋅ d 2 ans=\sum\limits_{d=0}^{\lfloor\frac{n-1}{2}\rfloor}(n^2d!-d!4nd+d!4d^2)\\ =n^2\sum\limits_{d=0}^{\lfloor\frac{n-1}{2}\rfloor}d!-4n\sum\limits_{d=0}^{\lfloor\frac{n-1}{2}\rfloor}d!\cdot d+4\sum\limits_{d=0}^{\lfloor\frac{n-1}{2}\rfloor}d!\cdot d^2 ans=d=02n1(n2d!d!4nd+d!4d2)=n2d=02n1d!4nd=02n1d!d+4d=02n1d!d2
    于是只需要预处理三个 ∑ \sum 的前缀和就能 O ( 1 ) O(1) O(1) 询问啦。总时间复杂度 O ( n + T ) O(n+T) O(n+T)

    实现

    注意阶乘求和不要忘了 0 0 0 的阶乘。long long 要开够。

    然鹅我把 ⌊ n − 1 2 ⌋ \lfloor\frac{n-1}{2}\rfloor 2n1 写成了 ⌊ n 2 ⌋ \lfloor\frac{n}{2}\rfloor 2n 竟然还过了。

    #include 
    using namespace std;
    typedef long long LL;
    const int N = 1000005;
    const LL mod = 10086001;
    int T;
    LL f1[N], f2[N], sf[N], n;
    void init() {
    	sf[0] = 1;
    	for (LL i = 1, fac = 1; i < (N >> 1); i++, fac = fac * i % mod)
    		sf[i] = (sf[i - 1] + fac) % mod,
    		f1[i] = (f1[i - 1] + i * i % mod * fac) % mod,
    		f2[i] = (f2[i - 1] + i * fac) % mod;
    }
    int main() {
    	init();
    	scanf("%d", &T);
    	while (T--)
    		scanf("%lld", &n),
    		printf("%lld\n", ((n * n % mod * sf[(n - 1) >> 1] % mod + 4 * f1[(n - 1) >> 1] % mod - 4 * n * f2[(n - 1) >> 1] % mod) % mod + mod) % mod);
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    总结

    • 这题只要敢推式子就能做。思路非常明显。
  • 相关阅读:
    使用Fiddler对手机App抓包
    云计算HCIA学习笔记-云计算基础概念
    SpringBoot教程(十三) SpringBoot集成MybatisPlus
    C++ 函数
    【计算机三级信息安全】信息安全保障概述
    Iphone自带的邮箱 每次发完邮件在已发送里会显示重复发送了两封
    倍福TwinCAT3 Ads相关错误详细列表
    03.使用引号来监听对象嵌套值的变化
    宜搭低代码开发高级认证例题1-待办列表
    人工智能的十个重大数理问题
  • 原文地址:https://blog.csdn.net/inferior_hjx/article/details/133148651