ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

20210819 Emotional Flutter,Medium Counting,Huge Counting,字符消除2

2021-08-20 07:00:49  阅读:247  来源: 互联网

标签:Huge Medium int LL T2 pos T1 kmp Counting


考场

T1 一下想到了这题,将白块缩短 \(s\) 后维护类似的区间即可。
T2 T3 俩计数,直接跳了。
T4 的可行 \(t\) 集合相同相当与从 \(n\) 往前跳 kmp 数组,途径点相同,从前往后构造即可。

问题是可能会出现一个区间分裂成好几个(开个队列),\(k\) 很小而 \(a_i\) 很大(每次跳到块尾),然后一直调到 10.20 还过不了拍,先丢了。
写完 T2 T3 俩暴力,发现 T4 \(2\times kmp[i]<i\) 的时候中间不知道填啥,不能全填 \(0/1\),然后一直手玩样例,三个样例总有一个过不去。。。
快结束的时候看了眼 T1,把每次跳到块尾的操作删了就过拍了,想着题面说数据有梯度,就交了个宁愿 T 的

res

rk19 0+0+15+0
T1 T2 全 T 了
T4 就是中间部分错了

rk1 yzf 100+100+40+20
rk2 szs 100+0+100+0
rk5 zjj 90+0+10+0
rk5 mtr 100+0+0+0
rk10 ycx 10+0+10+30
rk18 zkx 0+0+25+0

总结

其实没啥说的,就是菜

这场前面的人基本都 A 了 T1,但我考场上完全没往同余上想,有一个思路就面向数据编程,一直调,这样极容易暴毙,以后只有在确定算法正确性、复杂度的情况且其他题打满暴力的情况下再肝题。

这次虽然打了暴力但 T2 全 T 了,打暴力也算下复杂度,如果卡的紧就尽量剪剪枝。

sol

T1

每次跳到的位置模 \(k\) 同余,将黑块延长 \(s\) 后模 \(k\),如果 \([0,k)\) 中出现了一个点没被黑块覆盖说明有解。细节比较多。

const int N = 5e5+5;
int T,s,k,n;

PII f[N*2];

void solve() {
	int cnt = 0; LL now = 0; bool flg = 0;
	read(s,k,n); assert(k>s);
	For(i,1,n) {
		int len; read(len);
		if( i & 1 ) {
			LL l = now+1, r = now+len+s-1;
			if( r-l+1 >= k-1 ) flg = 1;
			l %= k, r %= k;
			if( l <= r ) f[++cnt] = MP(l,r);
			else f[++cnt] = MP(0,r), f[++cnt] = MP(l,k-1);
		}
		now += len;
	}
	if( flg ) return puts("NIE"), void();
	sort(f+1,f+cnt+1);
	For(i,2,cnt) assert(f[i].fi!=f[i-1].fi||f[i].se>=f[i-1].se);
	For(i,1,cnt) {
		ckmax(f[i].se,f[i-1].se);
		if( f[i-1].se+1 < f[i].fi ) return puts("TAK"), void();
	}
	puts(f[cnt].se+1<k ? "TAK" : "NIE");
}

signed main() {
	f[0].se = -1;
	read(T);
	while( T-- ) solve();
	return iocl();
}
T2

由于字典序从前往后比,即前面的影响更大,考虑从后往前 DP。设 \(f[i,j,l,r]\) 为第 \(l\) 个字符串到第 \(f\) 个,后缀 \(i\) 填完,当前这位至少是字符 \(j\) 的方案数

const int N = 55, L = 25, mod = 990804011;
int n;
char s[N][L];

int m;
LL f[L][30][N][N];

signed main() {
	scanf("%d",&n);
	For(i,1,n) {
		scanf("%s",s[i]+1);
		ckmax(m,(int)strlen(s[i]+1));
	}
	For(i,1,n) {
		For(j,1,m) if( !s[i][j] ) s[i][j] = 'a'-1;
		For(j,0,26) f[m+1][j][i][i] = 1;
	}
	rFor(i,m,1) rFor(j,26,0) rFor(l,n,1) For(r,l,n) {
		LL &dp = f[i][j][l][r];
		dp += f[i][j+1][l][r];
		for(int mid = l; (s[mid][i]=='a'+j-1||s[mid][i]=='?') && mid <= r; ++mid) {
			if( s[mid][i] == '?' && !j ) break;
			dp += f[i+1][0][l][mid] * (mid==r?1:f[i][j+1][mid+1][r]) %mod;
		}
		dp %= mod;
	}
	write(f[1][0][1][n]);
	return iocl();
}
T3
const int mod = 990804011;
int T,k;
LL l[9],r[9];

int all;
LL n[9],f[51][1<<10];

template<typename T>void ckadd(T &x,T y)
	{ x += y; if(x>=mod) x-=mod; else if(x<0) x+=mod; }

LL dfs(int u,int lim) {
	if( !u ) return 1;
	if( ~f[u][lim] ) return f[u][lim];
	int lim1 = 0;
	For(i,0,k) if( (lim & (1<<i)) && !(n[i] & (1ll<<u-1)) ) lim1 |= 1<<i;
	LL res = dfs(u-1,lim1);
	For(i,0,k) if( !(lim & (1<<i)) || (n[i] & (1ll<<u-1)) )
		ckadd(res,dfs(u-1,lim&(1<<i) ? lim1|(1<<i) : lim1));
	return f[u][lim] = res;
}
void solve() {
	LL ans = 0;
	read(k); all = (1<<k--)-1;
	For(i,0,k) read(l[i],r[i]), --l[i], --r[i];
	for(int s = all; ~s; --s) {
		int cnt = 0; memset(f,0xff,sizeof f);
		For(i,0,k)
			if( s & (1<<i) ) n[i] = r[i];
			else ++cnt, n[i] = l[i]-1;
		if( *min_element(n,n+k+1) >= 0 ) ckadd(ans,(cnt&1?-1:1) * dfs(50,all));
	}
	write(ans);
}

signed main() {
	read(T);
	while( T-- ) solve();
	return iocl();
}
T4

考虑贪心,那么中间部分一定全填 \(0\),否则最后一位填 \(1\) 即可,能否全填 \(0\) 可以填出来后暴力 kmp,看与原串是否一样。

证明:题解给了个挂掉的链接。。。

const int N = 2e5+1;
int T;
char s[N];

int n,n1,f[N],g[N],pos[N];

void kmp(int *nxt,int l,int r) {
	for(int i = l+1, j = nxt[l]; i <= r; ++i) {
		while( j && s[j+1] != s[i] ) j = nxt[j];
		if( s[j+1] == s[i] ) ++j;
		nxt[i] = j;
	}
}
bool check(int u) {
	for(; u; u = f[u]) if( f[u] != g[u] ) return 0;
	return 1;
}
void solve() {
	scanf("%s",s+1); n = strlen(s+1);
	kmp(f,1,n);
	For(i,1,n) s[i] = '0'; s[n+1] = 0;
	for(int i = n; i; i = f[i]) pos[++n1] = i; reverse(pos+1,pos+n1+1);
	s[pos[1]] = '0'+(pos[1]!=1), kmp(g,1,pos[1]);
	For(i,2,n1) {
		if( pos[i-1]*2 >= pos[i] )
			For(j,pos[i-1]+1,pos[i]) s[j] = s[pos[i-1]-(pos[i]-j)];
		else {
			For(j,pos[i]-pos[i-1]+1,pos[i]) s[j] = s[pos[i-1]-(pos[i]-j)];
			kmp(g,pos[i-1],pos[i]);
			if( !check(pos[i]) ) s[pos[i]-pos[i-1]] = '1';
		}
		kmp(g,pos[i-1],pos[i]);
	}
	printf("%s\n",s+1);
}

signed main() {
	scanf("%d",&T);
	while( T-- ) {
		n1 = 0;
		solve();
	}
	return iocl();
}

吐嘈

T1 题面说的“数据有梯度”恐怕指的是一个测试点内每组数据有梯度,不会正解的人只能拿到 0/10pts,导致今天爆 \(0\) 的人格外多。

虽然这次的题是拼的,但看 T2 T3 的原比赛出了 \(3\) 道计数,让我这种计数很弱的人体验极差。

T4 貌似是模拟赛中第一次出构造

标签:Huge,Medium,int,LL,T2,pos,T1,kmp,Counting
来源: https://www.cnblogs.com/401rk8/p/noip0820.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有