牛客的Latex问题好多,完全没法用。由于你逆天牛反复屏蔽我剪贴板链接,我只能放个图片了。**************

alt

alt

alt

alt 以下是文本.

题解 | #木棍#

逆天,怎么这题都是神仙做法?又是矩阵又是拉格朗日插值的。

实际上很简单就可以

由于我个人习惯,以下OI中更常用的记号 表示 。注意上下是相反的。

不妨设原木棍长为 ,变出来的木棍为 p,q,r ,不妨设 s<p<q<r <= 4s。

不难注意到,合法的情况远远多于不合法的情况。所以我们考虑正难则反,由于我们已经认定了 s<p<q<r <= 4s,首先总方案数是在[s+1,4s] 选三个不同数,排序得到的方案数,所以是 。现在我们只要找出在同样的限制下,不合法的方案数。

容易发现,在我们的限制条件下,一个方案是不合法的,那么必须有:

s+p<= q

p+q<= r

r<= 4s

否则大的就可以和小的两个构成三角形。

那么我们可以枚举 ,然后每次可以 求出 都确定时,不合法的 的总数(也就是 4s-p-q+1),从而求出所有不合法的方案数,复杂度

考虑卡常,我们优化上下界,不枚举不符合限制的情况。

为什么要不枚举超出限制的情况呢?因为只有这样,我们这个式子里每一个才都会对不合法情况有贡献。

具体地,首先我们枚举 。那就先找 的范围。

由于 s+p <= q ,s<p ,可以得到:

4s>= r>= p+q >= s+2p

所以有

s+2p<= 4s

p<= 3s/2

(逆天,你牛Latex打不出加号!以下用--表示+)

由于都是整数,有 确定 的范围后,我们枚举 ,所以我们现在要在已知 的情况下求出 的范围。

因为 ,所以

已知 时,符合限制的不合法 满足 ,所以不合法的 个。

现在我们有了一个小常数 算法,写成式子就是:

我当时在场上把这暴力一打完,我大呼这题不就做完了??

如果你还没看出来,我们首先把后面那里【与 有关的项】与【与 无关的项】分离。

所以 对于每个 ,枚举 都会被算 次。所以原式等于

后面用等差数列求和:

这样我们就有了 做法。但这还不够。

大力展开:

还是一样的技巧,把与 无关的扔到外面去。

后面利用 和等差数列求和 :

这是不合法情况.所以合法方案数是:

手残可能打错公式,如公式与代码不一致请以代码为准.

#include<bits/stdc++.h>
#define int __int128//毒瘤操作
using namespace std;
const int mod = 1e9 + 7;
int n;
int tot;
int inva;//不合法情况
int qpow(int b, int e)
{
    int res = 1;
    while(e)
    {
        // printf("%lld\n", e);
        if(e & 1) (res *= b) %= mod;
        (b *= b) %= mod; e >>= 1;
    }
    return res;
}//快速幂其实可以不要,因为inv2和inv6都是常数.懒得改了.
int inv2, inv6;
template<class io>
inline void re(io &x)
{
    char c=getchar();x=0;
    while(c<48 || c>57)c=getchar();
    while(c>47 && c<58)x=(x<<3)+(x<<1)+(c&15),c=getchar();
    return;
}//快读
template<class io>
void wr(io x)
{
    io d=x/10;if(d)wr(d);
    putchar(x-(d<<3)-(d<<1)|48);return;
}//快写
signed main()
{
    // freopen("c.in", "r", stdin);
    re(n); inv2 = qpow(2, mod - 2); inv6 = qpow(6, mod - 2);
    tot = (3 * n) % mod * (3 * n - 1) % mod * (3 * n - 2) % mod * inv6 % mod;
    inva = (3*n/2 - n)*((n*n%mod + n)%mod * 9 * inv2 % mod + 1) % mod;
    int lim = 3*n/2;
    (inva += 2*lim*(lim + 1)%mod*(2*lim + 1)%mod*inv6%mod) %= mod;
    ((inva -= 2*n*(n + 1)%mod*(2*n + 1)%mod*inv6%mod) += mod) %= mod;
    (inva -= (3 + 6*n)*(n + 1 + lim)%mod*(lim - n)%mod*inv2%mod + mod) %= mod;
    (inva += mod) %= mod;
    wr((tot - inva + mod) % mod);
    return 0;
}