数学

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 $ 的时候不要搞错了

posted @ 2023-06-01 15:49  jingyu0929  阅读(18)  评论(0)    收藏  举报