数学
P2613 有理数取余
这个先可以转化成 $ \frac{b}{a} x \equiv 1 \pmod {19260817} $ ,然后因为 $ 19260817 $ 是质数,所以说就可以直接用费马小定理,快速幂求就可以了。
然后因为这一题的输入是非常的大的,所以在快读的时候需要处理一下,显而易见,如果 $ b\pmod {19260817} x \equiv a \pmod {19260817} $,那么 $ \frac{b}{a} x \equiv 1 \pmod {19260817} $ 就一定成立。
大概就是这么个样子,核心代码
lwl a = fr();
lwl b = fr();
if (b == 0){
wj;
return 0;
}
int ans = a * ksm(b,mod - 2) % mod;
P2606 排列计数
这一题的题意简化一下就是在 $ 1 $ ~ $ n $ 的排列中找出有多少个排列满足小根堆的性质。
然后就转化成了一个树形 $ dp $ (?),还是二叉树所以这里的 $ i * 2+ 1 $ 和 $ i * 2 $其实就相当于二叉树的左儿子和右儿子, $ dp $ 的转移方程就是:
- $ dp[ i ] = C { siz[i * 2] \choose siz[i] - 1} * dp[i * 2] * dp[i * 2 + 1]$
然后这一题一开始写的时候不知道 $ siz $ 该怎么求,看题解写的是
for (int i = 1; i <= n; i ++) {
siz[i] = 1;
}
for (int i = n; i >= 2; i --) {
siz[i >> 1] += siz[i];
}
但是没有看懂,于是乎写了一个暴力 $ dfs $ ,终究还是喜欢 $ dfs $ 。
然后就是这一题要开 $ long $ $ long $ 不然会寄,虽然我觉得我第一次提交的代码要开的地方已经开了,但是 $ subtask 1 $ 一个点都没有过(当然还有我数组开小了的原因),于是乎一气之下直接 # $ define $ $ int $ $ long $ $ long $ 了
然后就是一点 核心代码
void dfs(int u) {
if (u > n) return ;
dfs(ur);
dfs(ul);
siz[u] = siz[ur] + siz[ul] + 1;
}
for (int u = n; u >= 1; u --) {
dp[u] = get(siz[u] - 1,siz[ul]) * dp[ur] % mod * dp[ul] % mod;
}
P6521 pin
本来组合数不想写博客记录的,主要是 $ LaTeX $ 太难打,但是做到一道题,看了题解感觉思路确实妙,于是写写
这道题的题意还是非常简洁明了的,于是就分开枚举,先枚举一个地方相同的时候(注意这个时候不是指恰好有一个地方相同,而是只要相同就先加上,也就是说如果是“ $ 0010 $ ”和“ $ 0020 $ ”,在这里会被算两遍,这就交给后面的容斥就好了),这个枚举就比较暴力了,就是枚举哪一个位置,然后用 $ map $ 存一下字符的 $ hash $ 值的数量,然后最后统计一下
而两个位置和三个位置也这样统计就可以了,而由于题目说了输入的字符串没有重复,所以不用考虑四个相同的情况。
然后就有了三个 $ cnt $ 数组,最后的 $ ans[1] $ 就是 $ cnt[3] $ ,因为没有重复的字符,所以恰好一个不同的时候就是三个相同的情况,而 $ ans[2] $ 就需要容斥了,首先肯定总的是 $ cnt[2] $ ,然后可以发现,每当有一对三个位置都相同的字符串的时候,他会被重复算三次,而且这对字符是不符合条件的,所以就用 $ cnt[2] - ans[1] * 3 $ , $ ans[3] $ 也和这个差不多,就是要把 $ ans[2] $ 和 $ ans[1] $ 都减一遍,而 $ ans[4] $ 就是剩下的,所以用总的对数把 $ ans[1] $ 、 $ ans[2] $ 和 $ ans[3] $ 都减掉就是剩下的了。
代码比较好写,于是就不贴了,然后要注意的就是 $ hash $ 的时候不要搞错了

浙公网安备 33010602011771号