|
|
跟下面那道题比起来属于是纯纯的小清新题了,这就是原友出题人和原批出题人的差距。不过当时的 FFT 应该没有现在这么普及,就像原神在最初几年也没有引起轩然大波一样。
这种组合数取模肯定考虑卢卡斯定理,况且 $n \lt p^{10}$ 也算是提醒你了。 将 $n$ 和 $k$ 写成 $p$ 进制数 $\overline{n_N...n_0}$ 和 $\overline{k_N...k_0}$,根据卢卡斯定理有 $C_n^k=\prod_i{C_{n_i}^{k_i}}$。显然每个 $k_i$ 的贡献是可以分开算的。
令 $f_{i,j}$ 表示前 $i$ 位组合数累乘后 $\%p=j$ 的方案数,$g_{i,j}$ 表示使得 $C_{n_i}^k \%p = j$ 的 $k$ 的数量,转移是简单的: $$f_{i,j}=\sum_{(x\times y) \%p=j}{f_{i-1,x} g_{i,y}}$$ 这转移式和卷积的相似度可以与原神媲美了,然而这个下标是相乘而不是相加。 但这玩意属于是典中典了,直接把下标对 $p$ 的原根取对数就可以转化成相加了,具体见 “[SDOI2015]序列统计”。
重新定义一下,令当前选择的原根是 $G$。 令 $f_{i,j}$ 表示前 $i$ 位组合数累乘后 $\%p=G^j$ 的方案数,$g_{i,j}$ 表示使得 $C_{n_i}^k \%p = G^j$ 的 $k$ 的数量,将转移写成和卷积: $$F_i=\sum_{j\ge 0}{f_{i,j}x^j}\quad\quad G_i=\sum_{j\ge 0}{g_{i,j}x^j}$$ $$\Rightarrow F_{i}=\sum_{j\ge 0}(\sum_{(x+y)\%(p-1)=j}{f_{i-1,x} g_{i,y}})x^j=F_{i-1}G_i$$
大概就是这样,注意下标相加实际是指数相加,所以根据费马小定理对 $p-1$ 取模。以及这样卷积出来会有下标大于 $p-1$ 的项,及时合并到前面即可。 介于答案模数较小,使用 FFT 计算卷积,时间复杂度大概是 $O(10p\log(p))$。 勉强加入“超级无敌神仙炫酷无敌原神大王”豪华套餐。
题目1797 [国家集训队2012]binomial
10
1 条 评论
2023-08-05 18:39:20
|
|
|
数个月前说要写,鸽到现在,菜。 属于是惊世骇俗的神秘题了。 拿到式子直接开始乱推:
$$ \sum_{i=1}^{n}{\gcd(i,n)^x \mathrm{lcm}(i,n)^y}\\ $$ $$ =\sum_{i=1}^{n}{i^yn^y\gcd(i,n)^{x-y}}\\ $$ $$ =n^y\sum_{d|n}{d^{x-y}\sum_{i=1}^{n}{i^y[\gcd(i,n)=d]}}\\ $$ $$ =n^y\sum_{d|n}{d^{x-y}\sum_{i=1}^{\frac{n}{d}}{(id)^y[\gcd(i,\frac{n}{d})=1]}}\\ $$ $$ =n^y\sum_{d|n}{d^x\sum_{i=1}^{\frac{n}{d}}{i^y\sum_{k|i,k|\frac{n}{d}}{\mu(k)}}}\\ $$ $$ =n^y\sum_{d|n}{d^x\sum_{k|\frac{n}{d}}{\mu(k)\sum_{i=1}^{\frac{n}{dk}}{(ik)^y}}}\\ $$ $$ =n^y\sum_{d|n}{d^x\sum_{k|\frac{n}{d}}{\mu(k)k^y\sum_{i=1}^{\frac{n}{dk}}{i^y}}}\\ $$ $$ =n^y\sum_{d|n}{d^x\sum_{k|\frac{n}{d}}{\mu(k)k^yS(\frac{n}{dk},y)}}\\ $$
玩原神的人都知道 $S(\frac{n}{dk},y)$ 是个 $y+1$ 次多项式,这就是原神带给我骄傲的资本。记 $S=\sum_{i=0}^{y+1}{f_ix^i}$ 代入:
$$ =n^y\sum_{d|n}{d^x\sum_{k|\frac{n}{d}}{\mu(k)k^y\sum_{i=0}^{y+1}{f_i(\frac{n}{dk})^i}}}\\$$ $$ =n^y\sum_{i=0}^{y+1}{f_i\sum_{d|n}{d^x\sum_{k|\frac{n}{d}}{\mu(k)k^y{(\frac{n}{dk})^i}}}}\\$$ $$ =n^y\sum_{i=0}^{y+1}{f_i(\mu \cdot Id^y \ast Id^x \ast Id^i)_{(n)}}\\$$
三个函数卷积,纯纯的卷狗。 好在三个积性函数卷出来也是积性函数,于是 pollard_rho 出 $n$ 的所有质因子分开算。
$$(\mu \cdot Id^y \ast Id^x \ast Id^i)_{(p^c)}\\$$ $$ =\sum_{j=0}^{c}{\mu(p^j)p^{yj}\sum_{k=0}^{c-j}{p^{kx}p^{(c-j-k)i}}}\\$$ $$ =\sum_{k=0}^{c}{p^{ci+(x-i)k}}-p^y\sum_{k=0}^{c-1}{p^{(c-1)i+(x-i)k}}\\$$
两坨都是等比数列求和,好好好,玩原神玩的。 最后就是这个 $f_i$。 如果你玩原神,那么你就会伯努利数,那么就知道:
$$\sum_{i=1}^{n}{i^k}=\frac{1}{k+1}\sum_{j=0}^{k}{(-1)^jC_{k+1}^jB_jn^{k+1-j}}$$
其中 $B_j$ 是伯努利数,可以用 EGF 求:
$$B(x)=\sum_{i \ge 0}{B_i\frac{x^i}{i!}}=\frac{x}{e^x-1}$$
然后就结束了。原神,启动! 听说还很卡常,已加入“超级无敌神仙炫酷无敌原神大王”豪华套餐。
题目1770 [国家集训队2012]JZPKIL
10
评论
2023-08-01 21:43:41
|
|
|
两年前的我这么强吗,还会写 30pts,现在的我 30pts 都写不出来。这种字符串工业太可怕了! 好吧,其实做法的提示性很强,这个东西明摆着是让你根号分治的。难点在于维护而不在于贪心。 我先口胡一个东西看看对不对啊。跑 SA,设阈值是 $B$,然后 $\gt B$ 的直接二分出来 $\rm sa$ 范围,然后扔主席树上不停进行区间查询时间复杂度是 $\mathcal O(\frac{nq}{B}\log n)$ 的一个东西。然后 $\le B$ 的子串只有 $\Theta(nB)$ 个。怎么预处理来着? 哦好像题目里规定了 $\le B$ 的很少,$r-l$ 随机均匀这个性质咋用?是想告诉我默认 $\tilde O(r-l)=1000$ 吗? 那我是不是还是可以和上面那个东西一样暴力跑啊 /qd。 看一眼 myee 的题解,好像还真行,$X=50,Y=2000$ 的话这个东西的复杂度就是 $$\mathcal O(\frac{\log n}{Y-X}\int_X^Y \frac{n}{x}\, \mathrm d x) = \mathcal O(n\log n\frac{\ln Y - \ln X}{Y-X})$$ 我不会微积分啊,这个式子是抄的。写完这个一定要学一学微积分,要不然这种细致复杂度分析不会做 /ng。(学不会,开摆) 好像还有 $r-l\le X$ 的情况,这个咋办来着。 一般来说字符串这种东西可以反着来,想一想出题人会怎么卡。他要卡我的话肯定能匹配的越多越好,那这样的话询问的本质不同串是不是不会多。 看题解。好吧,首先按上面的方法找到第一个位置,然后倍增预处理就行。不想写代码,啥时候闲的蛋疼了再写。
题目2937 [HAOI 2018]字串覆盖
4
评论
2023-07-22 17:52:06
|
|
|
从整张图入手,有两种方法可以得出这道题的结论。 高斯消元:把矩阵列出来,不难发现矩阵的秩为 $n-1$,那么方案数即为 $2^{m-n+1}$。 构造法:我们考虑一棵树。根据经典的剥叶子型构造手法,我们可以得出一棵树的时候方案数唯一,除非要求 $1$ 的点数为奇数,那样状态异或和为 $1$,而我们的操作状态异或和始终为 $0$,所以构造不出来。反之我们随便抽出来一棵生成树,对于其它边,显然取或不取只会反转两个点的状态,而我们的构造法永远可以构造出唯一解,所以方案数就是 $2^{m-n+1}$。 然后我们考虑这个原问题。图上就那么几个知识点,这题又和割点强相关,那就考虑广义圆方树。 假设一开始有 $\rm cnt$ 个连通块,$i$ 有 $\mathrm{deg}_i$ 条连边,和 $\mathrm{cut}_i$ 个方点相连,并且 $i$ 断开后没有一个连通块内有奇点,那么方案数就是 $2^{m-n-\mathrm{deg}_i+\mathrm{cnt}+1+\mathrm{cut}_i}$。时间复杂度 $\mathcal O(Tn)$。甚至不用显式地建出来圆方树,因为我们只需要 $\rm sz$ 和 $\rm cut$ 两个数组,直接求割点就行。
题目2936 [HAOI 2018]反色游戏
AAAAAAAAAA
5
评论
2023-07-22 16:19:47
|
|
|
算法:字符串哈希 方法通过将字符串的每一位字符转化为一个P进制数(P一般取较大的素数,如131,1007等)取模或用$unsigned long long$自然溢出,再利用前缀和求区间和进行匹配
参考代码:
#include <bits/stdc++.h>
using namespace std;
typedef unsigned long long ULL;
int res;
string s;
int const P=131; //这里使用131进制数
ULL p[1000010],f[1000010]; //转化进制是用的数组和前缀和数组
int main(){
f[0]=0,p[0]=1;
cin>>s;
s=" "+s;
for (int i=1;i<=s.length();i++){
f[i]=f[i-1]*P+(s[i]-'a'+1); //将s转化为数
p[i]=p[i-1]*P; //和转化进制的方式相似
}
int n;
ULL res1,res2;
scanf("%d",&n);
int l1,l2,r1,r2;
for (int i=1;i<=n;i++){
scanf("%d %d %d %d",&l1,&r1,&l2,&r2);
res1=f[r1]-f[l1-1]*p[r1-l1+1];
res2=f[r2]-f[l2-1]*p[r2-l2+1];
if (res1==res2) printf("Yes\n");
else printf("No\n");
}
return 0;
}
题目3151 兔子与兔子
6
评论
2023-07-21 17:05:59
|
|
|
这是一个 $k + 1$ 维偏序问题,如果使用 CDQ 分治的话将收获 $\mathcal O(n\log^k n)$ 的复杂度,而 $n = 40000$ 的情况下 $\log^k n$ 在这题已经是 $10^6$ 的量级,甚至跑不过暴力 $\mathcal O(n^2k)$。 考虑 bitset,我们用 $S_i$ 的一个 bitset 存储当前所有维度均小于 $i$ 的节点,每次对新的维度排序,然后 bitset and 一下即可。不难发现这样可以正确维护。 时间复杂度 $\mathcal O(\frac{n^2k}{\omega})$,其中 $\omega$ 是计算机位数,一般取 $\omega = 32\ \mathrm{or}\ 64$,跑得飞快,比一些实现的不好的 KDTree 正解还要快。
题目2639 [HZOI 2015] 偏序++
AAAAAAAAAA
6
评论
2023-07-16 10:41:47
|