首页 > 其他分享 >闲话 23.1.17

闲话 23.1.17

时间:2023-01-17 13:55:53浏览次数:66  
标签:return 17 int 闲话 sum long 23.1 PK using

闲话

今日推歌(?)
挺有味道的!

一会儿再补吧。

数学 \(3\)

怎么说?算了不感谢了
题解.txt:skyh's blog

彳亍

解方程

上来以为是分拆数假了一阵子。后来发现这个东西如果没有小于等于 \(a_i\) 的限制后就是插板法算组合数,因此考虑往那个方向转化。

首先为了凑出插板法需要让所有 \(X_i\) 取值从 \(0\) 开始,因此首先让 \(m\) 减去 \(n\)。\(n_1+1\sim n_2\) 没啥用,直接让 \(m\) 减去 \(a_i\) 后这部分的取值是任意的。注意先前已经减去一个 \(1\) 了。

随后考虑容斥。我们直接做子集反演,设集合 \(S\) 对应的状态 \(f(S)\) 表示钦定 \(|S|\) 个值不满足条件,剩下的值随便的计数。答案就是 \(\sum (-1)^{|T|} f(T)\)。
\(f(T)\) 是易求的,我们只需要将不满足条件的值如上地处理掉,剩下的就是随意划分了。假设这种情况下 \(m\) 剩余了 \(sum\),答案就是 \(\dbinom{sum + n - 1}{n - 1}\)。

由于模数的质因子都是小质数,因此可以采用 exLucas 解决。

code
#include <bits/stdc++.h>
using namespace std; 
#define int long long
using pii = pair<int, int>; using vi = vector<int>; using vp = vector<pii>; using ll = long long; 
using ull = unsigned long long; using db = double; using ld = long double; using lll = __int128_t;
#define multi int T; cin >> T; while ( T -- )
#define timer cerr << 1. * clock() / CLOCKS_PER_SEC << '\n';
#define iot ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
#define file(x) freopen(#x".in", "r", stdin), freopen(#x".out", "w", stdout)
#define rep(i, s, t) for (register int i = (s), i##_ = (t) + 1; i < i##_; ++ i)
#define pre(i, s, t) for (register int i = (s), i##_ = (t) - 1; i > i##_; -- i)
#define eb emplace_back
#define pb pop_back
const int inf = 0x3f3f3f3f;
const ll infll = 0x3f3f3f3f3f3f3f3fll;
int p, n, n1, n2, m, a[50], ans;

int exgcd(int a, int b, int &x, int &y) {
    if (b == 0)  {
    	x = 1, y = 0;
    	return a;
	} int d = exgcd(b, a % b, x, y);
    int tmp = x;
	x = y; y = tmp - a/b*y; 
	return d;
}
inline int lcm(int a, int b) {
    return a / __gcd(a, b) * b;
}
inline int inv(int a, int p) {
    int x, y;
    exgcd(a, p, x, y);
    return (x + p) % p;
}
inline int qp(int a, int b, int p) {
    int ret = 1; a %= p;
    while (b) {
        if (b & 1) ret = ret * a % p;
        b >>= 1;
		a = a * a % p;
    } return ret;
}

inline int F(int n, int P, int PK) {
    if (n == 0) return 1;
    int rou = 1;
    int rem = 1; 
    rep(i, 1, PK) if (i % P != 0) rou = rou * i % PK;
    rou = qp(rou, n/PK, PK);
    rep(i, PK * (n / PK), n) if (i % P != 0) rem = rem * (i % PK) % PK;
    return F(n / P, P, PK) * rou % PK * rem % PK;
}
inline int G(int n, int P) {
    if (n < P) return 0;
    return G(n/P, P) + (n/P);
}

inline int C_PK(int n, int m, int P, int PK) {
    int fz  = F(n, P, PK), 
		fm1 = inv(F(m, P, PK), PK), 
		fm2 = inv(F(n - m, P, PK), PK);
    int mi = qp(P, G(n, P) - G(m, P) - G(n - m, P), PK);
    return 1ll * fz * fm1 % PK * fm2 % PK * mi % PK;
} 

int A[1001], B[1001], tot;
inline int C(int n, int m, int P) {
    int tmp = P; tot = 0;
    for (int i=2; i * i <= P; i++) {
        if (tmp % i == 0) {
            int PK=1;
            while (tmp % i == 0) {
                PK *= i;
				tmp /= i;
            } A[++tot] = PK;
			B[tot] = C_PK(n, m, i, PK);
        }
    } if (tmp != 1) {
        A[++tot] = tmp;
		B[tot] = C_PK(n, m, tmp, tmp);
    } int ans = 0;
    rep(i, 1, tot) {
        int M = P / A[i], T = inv(M, A[i]);
        ans = (ans + 1ll * B[i] * M % P * T % P) % P;
    } return ans;
}

signed main() {
	int T; cin >> T >> p;
	while (T --) {
		ans = 0;
		cin >> n >> n1 >> n2 >> m; m -= n;
		rep(i, 1, n1+n2) cin >> a[i];
		rep(i, n1+1, n1 + n2) m -= a[i] - 1;
		if (n == 0 or m < 0) { puts("0"); continue; }
		rep(i, 0, (1<<n1)-1) {
			int now = m;
			rep(j, 0, n1-1) if ((i >> j) & 1) now -= a[j + 1];
			if (now < 0) continue;
			if (__builtin_popcount(i) & 1) 
				 ans = (ans - C(n + now - 1, n - 1, p) + p) % p;
			else ans = (ans + C(n + now - 1, n - 1, p)) % p;
		} cout << ans << '\n';
	} timer;
} 



宇宙序列

刚学完 FWT 就考欸 好耶

容易发现 \(a_i\) 序列是 \(a_1\) 序列自卷了 \(i\) 次。
由于异或卷积有结合律,我们可以直接作倍增,这样的时间复杂度是 \(O(pn2^n)\) 的。

由于 FWT 是线性变换,倍增时可以一直通过累加 \(\text{FWT}(a_1)\) 数组来得到答案。我们首先将 \(a_1\) 序列做 FWT,然后每位不断自乘后累加在 \(b\) 序列的对应位上,最后再将 \(b\) 序列做 IFWT 就得到了答案。
这样就优化到了 \(O(n2^n + q2^n)\)。

观察上一个做法,可以发现复杂度出现在不断自乘上。换句话说,我们需要优化的就是

\[b_k = \sum_{i=0}^{p} a_k^{2^{i}} \]

因为我想到这时没考虑 p 不是 2 的次方形式,所以考虑分治,我们要求的是 \(\sum_{i=0}^{2^k - 1} a^{2^i}\)。
我们做类似矩阵快速幂的做法,将前一半和后一半分开,也就得到了

\[\begin{aligned} &\sum_{i=0}^{2^k - 1} a^{2^i} \\ = \ & \sum_{i=0}^{2^{k-1} - 1} a^{2^i} + \sum_{i=2^{k-1}}^{2^{k} - 1} a^{2^i} \\ = \ & \sum_{i=0}^{2^{k-1} - 1} a^{2^i} + \sum_{i=0}^{2^{k} - 2^{k-1} 1} a^{2^{i+2^{k-1}}} \\ = \ & \sum_{i=0}^{2^{k-1} - 1} a^{2^i} + \sum_{i=0}^{2^{k-1} 1} a^{2^{i} \times 2^{2^{k-1}}} \\ = \ & \sum_{i=0}^{2^{k-1} - 1} a^{2^i} + \sum_{i=0}^{2^{k-1} 1} \left( a^{2^{2^{k-1}}} \right) ^{2^i} \end{aligned}\]

可以发现这个东西前后是同构的。我们设 \(f(a, k) = \sum_{i=0}^{2^k - 1} a^{2^i}\),则贡献有很奇妙的转移:

\[f(a, k) = f(a, k - 1) + f(a^{2^{2^{k-1}}}, k - 1) \]

由于模数很小,所以这个东西可以 \(O(\text{mod}\log p)\) 地统计得到。

到这我突然发现 \(p\) 不是 \(2^k\)。然后我摆了
然后其实对于任意 \(p\) 我们可以通过按位处理来得到值,复杂度为 \(O(\log p)\)。
得到 \(O(2^n)\) 个值后我们就可以 IFWT 回去了。

总时间复杂度 \(O(n2^n + \text{mod}\log p + 2^n \log p)\)。
代码挺短的,但是比较难调(谁让你摆了一上午最后半小时调啊

预处理部分似乎可以 \(O(\text{mod}^2)\) 地找循环节得到。看不懂,有想了解的可以问 lyin。

code
#include <bits/stdc++.h>
using namespace std; 
using pii = pair<int,int>; using vi = vector<int>; using vp = vector<pii>; using ll = long long; 
using ull = unsigned long long; using db = double; using ld = long double; using lll = __int128_t;
#define multi int T; cin >> T; while ( T -- )
#define timer cerr << 1. * clock() / CLOCKS_PER_SEC << '\n';
#define iot ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
#define file(x) freopen(#x".in", "r", stdin), freopen(#x".out", "w", stdout)
#define rep(i,s,t) for (register int i = (s), i##_ = (t) + 1; i < i##_; ++ i)
#define pre(i,s,t) for (register int i = (s), i##_ = (t) - 1; i > i##_; -- i)
#define eb emplace_back
#define pb pop_back
const int N = 1e6 + 10, mod = 10007, phi_1 = 5002;
const int inf = 0x3f3f3f3f;
const ll infll = 0x3f3f3f3f3f3f3f3fll;
using poly = vector<int>;
int n, len, p, q, ans, f[10007][32];
poly A, B;

int qp(int a, int b, int p = mod) {
	int ret = 1;
	while (b > 0) {
		if (b & 1) ret = 1ll * ret * a % p;
		a = 1ll * a * a % p;
		b >>= 1;
	} return ret;
}

void FWT(poly& A, const int& len, int typ = 1) {
    if (typ != 1) typ = (mod + 1) >> 1;
    for (int mid = 1, t; mid < len; mid <<= 1) 
        for (int i = 1, j = 0; j < len; j += (mid << 1)) 
            for (int k = 0; k < mid; ++ k) 
                t = A[j + k + mid],
                A[j + k + mid] = 1ll * (A[j + k] - t + mod) * typ % mod,
                A[j + k] = 1ll * (A[j + k] + t) * typ % mod;
}

signed main() {
	iot; cin >> n >> p >> q; len = 1 << n;
    A.resize(len), B.resize(len);
    rep(i,0,len-1) cin >> A[i]; 
	FWT(A, len, 1);
	rep(i,0,mod-1) f[i][0] = i;
	rep(j,1,30) rep(i,0,mod-1) 
		f[i][j] = (f[i][j - 1] + 
			f[qp(i, qp(2, (1 << j - 1) % phi_1, mod - 1), mod)][j - 1]) % mod;
	rep(i,0,len-1) {
		int tmp = 0;
		rep(j,0,30) if ((p + 1) >> j & 1) {
			B[i] = (B[i] + f[qp(A[i] , qp( 2 , tmp , mod - 1 ) , mod)][j]) % mod;
			tmp = (tmp + (1 << j)) % phi_1;
		}
	} 
	FWT(B, len, 0);
	cout << B[q] << '\n';
	timer;
}



exp

奇妙概率 dp。先咕着,晚点再写。

标签:return,17,int,闲话,sum,long,23.1,PK,using
From: https://www.cnblogs.com/joke3579/p/chitchat230117.html

相关文章

  • CF1748B题解
    题目传送门简要题意给定一个长度为\(n\)的只由数字\(0\)到\(9\)组成的字符串\(s\),求\(s\)中有多少个子串满足所有数字出现次数的最大值小于等于出现的不同数......
  • t团队日常记录 20230117
    上次记录是14号,中间调整了下,感觉从技术框架技术栈上也进行了突破。整体上要花费的时间成本也是跟上班差不多的,之前不管是在北京还是上海工作,都要在路上浪费一定的时间,......
  • 17.Selenium【单/复选框】单选框(Radio)复选框(CheckBox)
    一、前言单选框叫radio复选框叫checkbox区别就是单选框的选项是互斥的,也就是说你只能选一个选项类似于单选题。同理复选框类似多选题想怎么选就怎么选。一般情况下这......
  • CF1748B-Diverse Substrings
    长度为n的字符串,求出子串(只能从头尾依次删字符来得到子串)中,相同字符出现的最高次数小于等于不同字符的个数,这样的子串的个数以1~n个字符作为起点,枚举终点的位置来判断每种......
  • 2023年1月17日学习笔记
    转化AST树#整体框架#一样的,我们可以首先搭出大体的框架,具体的同类型的节点访问(转化)方法后面再说。这里的转化思路就比较重要了:我们要如何在遍历旧的AST树时能将转化......
  • 力扣每日一题2023.1.16---1813. 句子相似性 III
    一个句子是由一些单词与它们之间的单个空格组成,且句子的开头和结尾没有多余空格。比方说,"HelloWorld" ,"HELLO" ,"helloworldhelloworld" 都是句子。每个单词都只 ......
  • CF 1779C Least Prefix Sum 题解
    CF链接:LeastPrefixSumLuogu链接:Least PrefixSum${\scr\color{CornflowerBlue}{\text{Solution}}}$先来解释一下题意:给定一个数组,问最少把多少个数变成相反数,......
  • 手写笔记17:错题整理“Full GC & 新生代 & 老年代”
    ......
  • 2023.1.15
    本周总结本周主要是还是了解图论相关的一些算法,补了一下组合计数专题。大主题图论,数论小专题二分图、欧拉路径,欧拉回路组合计数题目完成情况每个专题配了一到两道......
  • 2023.1.16[模板] 二次剩余
    2023.1.16二次剩余问题叙述给出N,p,求解方程$x^2\equivN$(\(modp\))且保证p是奇素数。算法流程解的数量首先,探究$x^2\equivN$这个方程解的数量,假设我们......