题目大意
求所有的串,满足其所有循环同构串中至少有一个串是回文串。
题解
第一步我就想偏了orz……我以为要分析这样串的性质……
考虑所有回文串,共有
个,我们考虑把每个回文串第一个字符挪到后面,不断进行这样的操作,直到形成了新的回文串为止。假设这样操作了
次,那么这个回文串的贡献就是
。
比如baab,一次变成aabb,第二次变成abba,是个回文串,因此这个回文串的贡献是2.
考虑原串的最小整周期为
,显然一个周期也是个回文串。若
为奇数,那么贡献就是
,否则贡献是
。
令
表示周期为
的因数的所有回文串个数,
表示最小整周期恰好为
的所有回文串个数。则有:
再令
表示最小整周期为
时的贡献,即
为奇数是
,否则
。于是先使用莫比乌斯反演计算出
,就可以统计答案了。
但是这样计算还是会超时,考虑后面那个sigma的性质。
当且仅当
为奇数且
为偶数。如果
是偶数,那么
也必然是偶数。此时考虑任意的奇数
,必然有
,而如果后面sigma中的
含有4这个因数的话
。因此:若
为偶数,
为奇数时后面的sigma取值为0.于是剩下来所有情况都是
了。
显然后面那个sigma也是个积性函数,于是就可以得到:
于是这题再用Pollard-Rho分解一下
就做完了。
#include <bits/stdc++.h>
namespace IOStream {
const int MAXR = 1 << 23;
char _READ_[MAXR], _PRINT_[MAXR];
int _READ_POS_, _PRINT_POS_, _READ_LEN_;
inline char readc() {
#ifndef ONLINE_JUDGE
return getchar();
#endif
if (!_READ_POS_) _READ_LEN_ = fread(_READ_, 1, MAXR, stdin);
char c = _READ_[_READ_POS_++];
if (_READ_POS_ == MAXR) _READ_POS_ = 0;
if (_READ_POS_ > _READ_LEN_) return 0;
return c;
}
template<typename T> inline void read(T &x) {
x = 0; register int flag = 1, c;
while (((c = readc()) < '0' || c > '9') && c != '-');
if (c == '-') flag = -1; else x = c - '0';
while ((c = readc()) >= '0' && c <= '9') x = x * 10 + c - '0';
x *= flag;
}
template<typename T1, typename ...T2> inline void read(T1 &a, T2 &...x) {
read(a), read(x...);
}
inline int reads(char *s) {
register int len = 0, c;
while (isspace(c = readc()) || !c);
s[len++] = c;
while (!isspace(c = readc()) && c) s[len++] = c;
s[len] = 0;
return len;
}
inline void ioflush() {
fwrite(_PRINT_, 1, _PRINT_POS_, stdout), _PRINT_POS_ = 0;
fflush(stdout);
}
inline void printc(char c) {
_PRINT_[_PRINT_POS_++] = c;
if (_PRINT_POS_ == MAXR) ioflush();
}
inline void prints(char *s) {
for (int i = 0; s[i]; i++) printc(s[i]);
}
template<typename T> inline void print(T x, char c = '\n') {
if (x < 0) printc('-'), x = -x;
if (x) {
static char sta[20];
register int tp = 0;
for (; x; x /= 10) sta[tp++] = x % 10 + '0';
while (tp > 0) printc(sta[--tp]);
} else printc('0');
printc(c);
}
template<typename T1, typename ...T2> inline void print(T1 x, T2... y) {
print(x, ' '), print(y...);
}
}
using namespace IOStream;
using namespace std;
typedef long long ll;
const int B = 10, prime[B] = { 2, 3, 5, 7, 11, 13, 17, 19, 23, 29 };
ll modmul(ll a, ll b, ll c) {
return (ll)((__int128)a * b % c);
}
ll modpowi(ll a, ll b, int c) {
ll res = 1;
for (a %= c; b; b >>= 1) {
if (b & 1) res = res * a % c;
a = a * a % c;
}
return res;
}
ll modpow(ll a, ll b, ll c) {
ll res = 1;
for (a %= c; b; b >>= 1) {
if (b & 1) res = modmul(res, a, c);
a = modmul(a, a, c);
}
return res;
}
int miller_rabin(ll p) {
for (int i = 0; i < B; i++) {
if (prime[i] == p) return 1;
else if (p % prime[i] == 0) return 0;
}
ll t = p - 1; int l = 0;
for (; !(t & 1); t >>= 1) ++l;
for (int i = 0; i < B; i++) {
ll x = modpow(prime[i], t, p);
for (int j = 0; j < l; j++) {
ll y = modmul(x, x, p);
if (y == 1 && x != 1 && x != p - 1) return 0;
x = y;
}
if (x != 1) return 0;
}
return 1;
}
ll pollard_rho(ll n) {
ll x, y = x = rand() % (n - 1) + 1, c = rand() % (n - 1) + 1, k = 1;
for (int i = 1;; i++) {
x = (modmul(x, x, n) + c) % n;
if (x == y) return 1;
ll g = __gcd(n, x < y ? y - x : x - y);
if (g > 1 && g < n) return g;
if (i == k) y = x, k <<= 1;
}
}
map<ll, int> mp;
vector<pair<ll, int> > vec;
void fact(ll n) {
if (miller_rabin(n)) { ++mp[n]; return; }
ll p; while ((p = pollard_rho(n)) == 1);
fact(p), fact(n / p);
}
ll ans, n, k; int T, p;
void dfs(int d, ll num, ll mul) {
if (d < 0) {
if ((num & 1) && !(n & 1)) return;
ll h = (num & 1 ? num : num >> 1) % p;
(ans += modpowi(k, (num + 1) >> 1, p) * mul % p * h) %= p;
return;
}
ll t = 1, q = vec[d].first, e = vec[d].second;
for (int i = 0; i <= e; i++, t *= q)
dfs(d - 1, num * t, mul * (i < e ? 1 - q : 1) % p);
}
int main() {
srand(time(0));
for (scanf("%d", &T); T--;) {
scanf("%lld%lld%d", &n, &k, &p);
if (n == 1) { printf("%lld\n", k % p); continue; }
mp.clear(), vec.clear(), ans = 0; fact(n);
for (auto a : mp) vec.push_back(a);
dfs(vec.size() - 1, 1, 1);
printf("%lld\n", (ans + p) % p);
}
return 0;
}