zoukankan      html  css  js  c++  java
  • [做题记录] Luogu P4607 [SDOI2018]反回文串 题解 HN

    题意

    「回文串什么的最讨厌了……」

    小 Q 讨厌任何形式的回文串:

    1. 如果一个字符串从左往右读和从右往左读是一样的,那么小 Q 讨厌它;例如 aaaba
    2. 对于一个字符串来说,若将某个前缀子串移除并拼接到字符串的尾部,能得到一个小 Q 讨厌的字符串,那么小 Q 也会讨厌原来的这个字符串;例如 aabbaa

    现在问题来了,如果任意字符串只可以由 \(k\) 种已知的字符组成 (也就是说字符集的大小为 \(k\) ),那么长度为 \(n\) 的所有字符串里,有多少字符串是小 Q 讨厌的?

    答案可能很大,你只需要给出答案对 \(p\) 取模后的值。

    \(T \leq 10, n, k\leq 10^{18}\) , \(p\) 不一定是素数。

    题解

    这是人做的????

    考虑一个计算答案的方式是枚举回文串, 然后这个回文串的所有循环移位进行一次贡献。

    但是这样显然会算重, 因为可能出现回文串之间的循环同构, 也有可能串在循环移位的时候会得到自身。

    考虑对于每一个回文串, 求一个最小的 \(l\) 使得这个串在循环移位 \(l\) 次以后会再次变成一个回文串, 那么 \(\sum l\) 就是答案。

    考虑 \(l\) 的取值在不同字符串下的情况。

    一个经典的想法是, 对于最小循环节 \(T\) , 如果 \(T\) 是偶数, 那么 \(l = \frac{T}{2}\) , 否则 \(l = T\)

    那么现在我们考虑对于最小循环节为某个数的字符串计数。

    考虑设 \(h(i) = 长度为i的字符串的l = i \times \frac{1 + [i是奇数]}{2}\)\(f(i)\) 表示最小循环节为 \(i\) 的字符串的个数。

    那么答案就是 :

    \[\sum_{d|n}f(d) h(d) \]

    又因为

    \[\sum_{d|n}f(d)=k^{\lceil\frac n2\rceil}=g(n) \]

    所以

    \[f(n) = \sum_{d|n}g(d) \mu(\frac{n}{d}) \\ ans = \sum_{i | n}g(i)\sum_{d | \frac{n}{i}}\mu(d)h(id) \]

    然后这里思路就又卡住了。

    考虑把 \(h(id)\) 拆开来看, 变成 \(d \times h(i)\)

    观察 \(h(id) \neq d \times h(i)\) 的时候当且仅当 \(d\) 为偶数, 且 \(i\) 为奇数, 注意此时 \(\frac{n}{i}\) 也是偶数。

    不妨考虑 \(i\) 为奇数, \(\frac{n}{i}\) 是偶数这个条件下, 下面式子的取值:

    \[\sum_{d|\frac{n}{i}}\mu(d)h(id) \]

    由于 \(\frac{n}{i}\) 是偶数, 所以可以对于 \(d\) 是否是偶数分别讨论, 发现此时 \(\mu\) 相反, \(h\) 相等, 恰好是 \(0\)

    那么可以变换原来的式子 :

    \[ans = \sum_{i|n}g(i)f(i)\sum_{d|\frac{n}{i}}d\mu(d) \]

    注意虽然前面说明了那个情况下没有贡献, 但是枚举的时候要注意 \(i\) 是奇数, \(\frac{n}{i}\) 是偶数的时候, 要跳过去。

    然后考虑后面那个东西, 其实就是把 \(\frac{n}{i}\) 质因数分解以后, 求 \(\prod_{i = 1}^k (1 - p_i)\) , 上 \(PR\) 即可。

    #include <bits/stdc++.h>
    
    using namespace std;
    
    #define lep(i, l, r) for(int i = (l); i <= (r); i ++)
    #define rep(i, l, r) for(int i = (l); i >= (r); i --)
    #define Lep(i, l, r) for(int i = (l); i <  (r); i ++)
    #define Rep(i, l, r) for(int i = (l - 1); i >= (r); i --)
    #define debug(...) fprintf (stderr, __VA_ARGS__)
    #define pb push_back
    #define fi first
    #define se second
    #define gc getchar
    #define pc putchar
    
    using i64 = long long;
    using uint = unsigned int;
    using ui64 = unsigned long long;
    using pii = std :: pair<int, int>;
    using vi = std :: vector<int>;
    #define int long long
    template<typename A, typename B>
    inline void Min(A &x, B y) { x = x < y ? x : y; }
    template<typename A, typename B>
    inline void Max(A &x, B y) { x = x > y ? x : y; }
    template<typename T> inline void read(T &x) {
    	x = 0; char a = gc(); bool f = 0;
    	for (; ! isdigit(a); a = gc()) if (a == '-') f = 1;
    	for (; isdigit(a); a = gc()) x = x * 10 + a - '0';
    	if (f) x = -x;
    }
    
    int P = 1e9 + 7;
    inline int mod(int x) { return x + (x >> 31 & P); }
    inline void sub(int &x, int y) { x = mod(x - y); }
    inline void pls(int &x, int y) { x = mod(x + y - P); }
    inline int add(int x, int y) { return mod(x + y - P); }
    inline int dec(int x, int y) { return mod(x - y); }
    inline int power(int x, i64 k) {
    	int res = 1; if (k < 0) k += P - 1;
    	while (k) { if (k & 1) res = 1ll * res * x % P; x = 1ll * x * x % P; k >>= 1; }
    	return res;
    }
    
    namespace Pollard_Rho_Space {
    	mt19937 Rand;
    	inline i64 mul(i64 x, i64 y, i64 P) {
    		//i64 res = x * y - (i64) ( (long double) x / P * y + 0.5 ) * P;
    		//return res < 0 ? res + P : res;
    		return (__int128) x * y % P;
    	}
    	inline i64 power(i64 x, i64 k, i64 P) {
    		i64 res = 1;
    		while(k) {
    			if(k & 1) res = mul(res, x, P);
    			x = mul(x, x, P); k >>= 1;
    		} return res;
    	}
    	inline bool Miller_Rabbin(i64 n) {
    		static int pri[10] = {2, 3, 5, 7, 11, 13, 17, 19, 23, 61};
    		lep (i, 0, 9) if(n % pri[i] == 0) return n == pri[i];
    		lep (i, 0, 9) {
    			i64 r = n - 1, b = 0;
    			while(! (r & 1)) r >>= 1, b ++;
    			i64 w = power(pri[i], r, n), p = w;
    			lep (j, 1, b) {
    				w = mul(w, w, n);
    				if(w == 1 && p != n - 1 && p != 1) return 0;
    				p = w;
    			}
    			if(w != 1) return 0;
    		}
    		return 1;
    	}
    	inline i64 run(i64 x, i64 n, i64 c) {
    		return (mul(x, x, n) + c) % n;
    	}
    	inline i64 Pollard(i64 n) {
    		if(n == 4) return 2;
    		i64 c = Rand() % (n - 1) + 1, a = 0, b = 0;
    		a = run(a, n, c);
    		b = run(b, n, c); b = run(b, n, c);
    		while(a ^ b) {
    			i64 g = __gcd(abs(a - b), n);
    			if(g != 1) return g;
    			a = run(a, n, c);
    			b = run(b, n, c); b = run(b, n, c);
    		}
    		return n;
    	}
    	inline i64 Pollard_Rho(i64 n) {
    		if(Miller_Rabbin(n)) return -1;
    		i64 res;
    		while((res = Pollard(n)) == n);
    		return res;
    	}
    }
    
    using Pollard_Rho_Space :: Pollard_Rho;
    using Pollard_Rho_Space :: Miller_Rabbin;
    
    const int N = 5e5 + 10;
    
    i64 stk[N];
    int top;
    i64 n, k;
    
    void getfactor(i64 n) {
    	if(n == 1) return ;
    	if(Miller_Rabbin(n)) { stk[++ top] = n; return ; }
    	i64 p = Pollard_Rho(n);
    	getfactor(n / p); getfactor(p);
    }
    
    i64 p[N], q[N];
    int cnt;
    
    i64 ans;
    
    int g(i64 n) { return power(k, (n + 1) / 2); }
    int h(i64 n) { return (n & 1 ? n : n >> 1) % P; }
    
    void dfs(int i, i64 d, i64 pr) {
    	//cerr << i << ' ' << d << ' ' << pr << endl;
    	
    	if(i == cnt + 1) {
    		if((n / d & 1) && (d & 1) == 0) return ;
    		ans = (ans + 1ll * g(n / d) * h(n / d) % P * pr % P) % P;
    		return ;
    	}
    	
    	dfs(i + 1, d, pr);
    	pr = 1ll * pr * (P - p[i] % P + 1) % P;
    	for(int j = 1; j <= q[i]; j ++) d *= p[i], dfs(i + 1, d, pr);
    }
    
    void solve() {
    	read(n); read(k); read(P);
    	k %= P;
    	top = 0;
    	getfactor(n); 
    	sort(stk + 1, stk + 1 + top);
    	cnt = 0;
    	for(int i = 1; i <= top; i ++) {
    		if(stk[i] != stk[i - 1]) p[++ cnt] = stk[i], q[cnt] = 0;
    		q[cnt] ++;
    	}
    	ans = 0; dfs(1, 1, 1); cout <<ans<<endl;
    }
    
    signed main() {
    	int Case; read(Case);
    	while(Case --) solve();
    	return 0;
    }
  • 相关阅读:
    WebHttpRequest在sharepoint文档库中的使用
    使用log4net无法将日志记录插入mysql数据库解决办法
    通过WebClient模拟post上传文件到服务器
    webservice测试窗体只能用于来自本地计算机的请求
    rest api方式实现对文档库的管理
    咏南中间件支持即时通讯
    QJSON封装好的序列和还原方法
    ADO特有的流化和还原
    FIREMONEY手机虚拟键盘遮挡的解决
    安卓安装ZXING(二维码)SDK
  • 原文地址:https://www.cnblogs.com/clover4/p/15713164.html
Copyright © 2011-2022 走看看