QOJ.ac

QOJ

ID题目提交者结果用时内存语言文件大小提交时间测评时间
#60536#4483. Count Setqinjianbin#AC ✓7333ms107012kbC++4.0kb2022-11-05 13:10:052022-11-05 13:10:08

Judging History

你现在查看的是最新测评结果

  • [2023-08-10 23:21:45]
  • System Update: QOJ starts to keep a history of the judgings of all the submissions.
  • [2022-11-05 13:10:08]
  • 评测
  • 测评结果:AC
  • 用时:7333ms
  • 内存:107012kb
  • [2022-11-05 13:10:05]
  • 提交

answer

#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>

#define lowbit(x) (x&(-x))
#define lx (x<<1)
#define rx (x<<1|1)

using namespace std;

typedef long long LL;
typedef unsigned long long uLL;

const int maxn = 1048576*2;
const int maxm = 100005;
const int mod = 998244353;
const int log2maxn = 33;
const LL inf = 1ll << 62;

int n, m, len;
int TanJI;

int p[maxn];
LL inv[maxn];
LL fact[maxn], invFact[maxn];

LL g[maxn];
LL f[maxn];
LL a[maxn], b[maxn] ,c[maxn];

int pos[maxn];

int cnt[maxn];

int head[maxn],L[maxn];

LL qpow(LL x, LL y)
{
	LL ans = 1;
	for (; y; y >>= 1, x = x * x % mod)
		if (y & 1) ans = ans * x % mod;
	return ans;
}

void preprocess(int len)
{
	int i;
	for (i = 1; i < len; i++)
		pos[i] = (pos[i >> 1] >> 1) | ((len >> 1) * (i & 1));
	g[0] = 1;
	g[1] = qpow(3, (mod - 1) / len);
	for (i = 2; i < len; i++)
		g[i] = g[i - 1] * g[1] % mod;
}

void FNTT(LL* a, bool flag, int len)
{
	int i, j, k, w;
	LL u, v;
	for (i = 1; i < len; i++)
		if (i < pos[i]) a[i] ^= a[pos[i]] ^= a[i] ^= a[pos[i]];
	for (i = 2; i <= len; i <<= 1)
		for (j = 0; j < len; j += i)
			for (w = k = 0; k < (i >> 1); k++, w += len / i)
			{
				u = a[j + k];
				v = a[j + (i >> 1) + k] * g[flag ? w : (len - w) % len] % mod;
				a[j + k] = (u + v) % mod;
				a[j + (i >> 1) + k] = (u - v) % mod;
			}
}

void mul(int n, int m)
{
	int i, len;
	for (len = 1; len < n + m - 1; len <<= 1);

	preprocess(len);
	for (i=n; i < len; i++) a[i] = 0;
	for (i=m; i < len; i++) b[i] = 0;

	FNTT(a, true, len);
	FNTT(b, true, len);
	for (i = 0; i < len; i++)
		c[i] = a[i] * b[i] % mod;
	FNTT(c, false, len);
	for (i = 0; i < len; i++)
	{
		c[i] = c[i] * inv[len] % mod;
		if (c[i]<0) c[i]+=mod;
	}
}

LL C(int n,int m)
{
	if (n<0||n<m) return 0;
	return fact[n]*invFact[m]%mod*invFact[n-m]%mod;
}

int pt[maxn];
int siz[maxn];

int get_root(int x)
{
	//return pt[x]==x?x:get_root(pt[x]);
	int y=x,r;
	while (pt[y]!=y) y=pt[y];
	r=y;
	while (pt[x]!=x)
	{
		y=pt[x];
		pt[x]=r;
		x=y;
	}
	return r;
}

void solve(int l,int r)
{
	if (l==r) return;
	
	int i,j;
	int mid=(l+r)>>1;
	
	solve(l,mid);
	solve(mid+1,r);
	
	a[0]=1;
	for(i=head[l],j=1;j<=L[l];i++,j++)
	{
		a[j]=f[i];
	}
	b[0]=1;
	for(i=head[mid+1],j=1;j<=L[mid+1];i++,j++)
	{
		b[j]=f[i];
	}
	
	mul(L[l]+1,L[mid+1]+1);
	L[l]+=L[mid+1];
    L[l]=min(L[l],TanJI);
	for(i=head[l],j=1;j<=L[l];i++,j++)
		f[i]=c[j];
}

void standing_by()
{
	int i,j,k;
	int u,v;

	scanf("%d%d", &n,&TanJI);
	for(i=1;i<=n;i++)
	{
		pt[i]=i;
		siz[i]=1;
        cnt[i]=0;
	}
	for(i=1;i<=n;i++)
	{
		scanf("%d",&p[i]);
		//p[i]=i%n+1;
		u=get_root(i);
		v=get_root(p[i]);
		if (u!=v)
		{
			pt[u]=v;
			siz[v]+=siz[u];
		}
	}
	
	for(i=1;i<=n;i++)
	{
		if (get_root(i)==i)
		{
			cnt[siz[i]]++;
		}
	}
	
    for(i=1;i<=m;i++) head[i]=L[i]=0;
    m=0;
	L[0]=1;
	for(i=2;i<=n;i++)
	{
        
		for(j=1;j<=cnt[i];j++)
		{
			++m;
			head[m]=head[m-1]+L[m-1];
			L[m]=min(i,TanJI);
			for(k=1;k<=L[m];k++)
				f[head[m]+k-1]=0;
            if (i>1&&L[m]>=1)
            {
                f[head[m]]=i;
            }
            if (i>=3&&L[m]>=2)
            {
                f[head[m]+1]=C(i,2)-i;
            }
			for(k=3;k<=L[m];k++)
			{
				f[head[m]+k-1]=(C(i-3-(k-2),k-1)+C((i-1-(k-1)),k))%mod;
			}
		}
	}
}
//21:16 
void complete()
{
	LL ans=0;
	if (m>=1)
	{
		solve(1,m);
		f[0]=1;
		ans=(f[TanJI]+mod)%mod;
	}else {
		if (TanJI==0)
			ans=1;
	}
	
	printf("%lld\n",ans);
}

int main()
{
    int t;
    int i;

	inv[1] = 1;
	fact[0] = fact[1] = invFact[0] = invFact[1] = 1;
	for (i = 2; i < maxn; i++)
	{
		inv[i] = mod - inv[mod % i] * (mod / i) % mod;
		fact[i] = fact[i - 1] * i % mod;
		invFact[i] = invFact[i - 1] * inv[i] % mod;
	}

    scanf("%d",&t);
    for(;t;t--)
	{
        standing_by();
	    complete();
    }
	return 0;
}

详细

Test #1:

score: 100
Accepted
time: 7333ms
memory: 107012kb

input:

14
5 1
5 3 2 1 4
5 2
2 5 1 3 4
10 3
10 9 3 8 6 4 5 7 2 1
30 5
1 16 28 30 27 23 2 20 10 12 7 13 11 15 17 24 14 25 21 4 22 29 3 6 19 18 8 26 9 5
30 5
29 6 21 30 14 18 24 26 3 11 23 13 2 12 16 9 4 22 25 20 28 19 5 17 8 10 15 1 7 27
500000 200000
293510 102358 252396 467703 280403 93120 462332 442364 31...

output:

5
5
40
51129
51359
371836159
565197945
0
0
844811446
803690398
638630160
14371218
1

result:

ok 14 lines