rt,下面是我的代码:
#include <iostream>
#include <cstring>
using namespace std;
typedef long long ll;
const int max_n = 1000, mod = int(1e9) + 7;
int a[max_n], hd[max_n], des[max_n<<1], nxt[max_n<<1], e_cnt, vis[max_n];
ll f[max_n+1];
void add(int s, int t)
{
des[e_cnt] = t;
nxt[e_cnt] = hd[s];
hd[s] = e_cnt++;
}
ll qpow(ll bs, ll ix)
{
ll cur = 1, mul = bs, ret = 1;
while (cur <= ix)
{
if (cur & ix)
ret = (ret * mul) % mod;
mul = (mul * mul) % mod;
cur <<= 1;
}
return ret;
}
void dfs(int id)
{
for (int p = hd[id]; p != -1; p = nxt[p])
if (!vis[des[p]])
{
vis[des[p]] = 114514191;
dfs(des[p]);
}
}
signed main()
{
ios_base::sync_with_stdio(false);
cin.tie(0);
int n, k, cas, cnt, ind, sti;
ll ans;
cin >> cas;
while (cas--)
{
memset(hd, -1, sizeof hd);
memset(vis, 0, sizeof vis);
cin >> n >> k, e_cnt = 0, cnt = 0;
for (int i = 0; i < n; i++)
{
cin >> a[i];
add(i, a[i]), add(a[i], i);
}
f[1] = k, f[2] = k * (k - 1), f[3] = f[2] * (k - 2) % mod;
for (int i = 4; i <= n; i++)
f[i] = (f[i-1] * (k - 2) + f[i-2] * (k - 1)) % mod;
ind = 1, ans = 1;
for (int i = 0, ptr; i < n; i++)
if (!vis[i])
{
ptr = i, sti = ind;
while (!vis[ptr])
{
vis[ptr] = ind++;
ptr = a[ptr];
}
if (sti <= vis[ptr])
{
ans = ans * f[ind-vis[ptr]] % mod;
cnt += ind - vis[ptr];
}
// do {
// dfs(ptr);
// ptr = a[ptr];
// } while (vis[ptr] < ind - 1);
}
cout << ans * qpow(k - 1, n - cnt) % mod << endl;
}
return 0;
}
注释部分是给基环树剩余部分打标记避免再次计算的,但加上这部分导致了 TLE。而删去后改用检查时间戳就过了。
题解好像都是这么写的,好像也不是性能问题,所以这是为什么呢?求助。