雅礼集训1.2 T1串
Posted tanjunming2020
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了雅礼集训1.2 T1串相关的知识,希望对你有一定的参考价值。
题目大意
给定一个由小写字母组成的字符串 s s s,每次你可以删去它的一个非回文子串,求删成空串的最小次数。
有 t t t组数据, 1 ≤ t ≤ 20 1\\leq t\\leq 20 1≤t≤20, 1 ≤ n ≤ 1 0 5 1\\leq n\\leq 10^5 1≤n≤105
题解
如果 s s s不是回文串,则答案为 1 1 1。
如果是回文串且满足下列三种情况的一种,则输出 − 1 -1 −1
- s s s由同一种字符构成,如 a a a a a a a a aaaaaaaa aaaaaaaa
- s s s的长度为奇数且除了最中间的字符,其他字符相同,如 a a a b a a a aaabaaa aaabaaa
- s s s由两种字符构成,且两种字符交替出现,如 a b a b a b a abababa abababa
如果不满足上述三种情况,则答案为 2 2 2。
时间复杂度为 O ( t n ) O(tn) O(tn)。
code
#include<bits/stdc++.h>
using namespace std;
int t,n;
char s[100005];
int main()
scanf("%d",&t);
while(t--)
scanf("%d",&n);
scanf("%s",s+1);
int v=0;
for(int i=1;i<=n/2;i++)
if(s[i]!=s[n-i+1])
v=1;break;
if(v==1)
printf("1\\n");
continue;
//不是回文串
v=0;
for(int i=2;i<=n;i++)
if(s[i]!=s[1])
v=1;break;
if(!v)
printf("-1\\n");
continue;
//第一种情况
if(n&1)
v=0;
for(int i=1;i<=n;i++)
if(i==n/2+1) continue;
if(s[i]!=s[1])
v=1;break;
if(!v)
printf("-1\\n");
continue;
//第二种情况
v=0;
for(int i=1;i<=n-2;i++)
if(s[i]!=s[i+2])
v=1;break;
if(!v)
printf("-1\\n");
continue;
//第三种情况
printf("2\\n");
return 0;
「6月雅礼集训 2017 Day5」吃干饭
【题目大意】
询问[L,R]中选若干个数异或起来得到的答案集合大小。多组数据。
对于50%的数据,$R - L \\leq 10^4$
对于100%的数据,$R - L \\leq 10^{18}, T \\leq 10^2$
【题解】
考虑50%的数据,暴力线性基即可。
这样的复杂度是$O(T(R-L)logn)$
观察到数据比较特殊,是连续的一段正整数,我们写完线性基暴力然后打个表观察数在什么时候被插入到线性基里。
我们以[23333, 66666]为例:
首先L=23333,这个数一定被插入到线性基的最高位
考虑线性基的每一位什么时候会变化
下面是每位被插入的时候的值,下方标有“.”的为被插入到线性基的哪一位
就大概这样一个过程,可以观察到每次插入线性基的下一个数,都是上一个数从后往前的最早一个0,满足它所在的位还没有被插入到线性基里,为了插入这个位,我们需要把它变成1,这个暴力算一下就好了。
然后我们最多插入log位,每次找从后往前第一个没有被插入到线性基里的0最多log的复杂度,总复杂度$O(Tlog^2C)$,其中C为数的范围。
还有另一种解法,这里提一下,代码实现极其简单就不写了。。
就是 ans[L,R] = ans[L/2, R/2] * 2 (R-L >= 3)。
相当于抹去线性基最后一位,由于区间长度比较长,所以线性基最后一位一定存在贡献。
当R-L>=3一定有贡献,R-L=2和=1的时候特判一下,递归下去做即可。复杂度$O(TlogC)$。
# include <stdio.h> # include <string.h> # include <iostream> # include <algorithm> using namespace std; typedef long long ll; typedef unsigned long long ull; typedef long double ld; const int M = 2e5 + 10, N = 1e5 + 10, F = 65 + 3; const int mod = 998244353; int n; // ll Lbase[F]; ll L, R; ll bin[F]; bool hv[F]; # define bit(x, i) (((x) >> (i)) & 1) inline ll getll() { ll x = 0; char ch = getchar(); while(!isdigit(ch)) ch = getchar(); while(isdigit(ch)) x = x*10 + ch - \'0\', ch = getchar(); return x; } /* inline void sol() { L = getll(), R = getll(); for (int i=62; ~i; --i) Lbase[i] = 0; for (int i=L; i<=R; ++i) { int x = i; for (int j=62; ~j; --j) { if(bit(x, j)) { if(Lbase[j] == 0) { Lbase[j] = x; // printf("base[ %d ] = %d, origin = %d \\n", j, x, i); break; } x ^= Lbase[j]; } } } int times = 0; for (int i=62; ~i; --i) if(Lbase[i] != 0) ++times; printf("%lld\\n", bin[times]); } */ int gpos; inline ll gnext(ll x) { // first 0 int pos = 0; for (int i=0; i<=62; ++i) { if(!bit(x, i) && !hv[i]) { pos = i; break; } } ll tem = 0; for (int i=pos; i>=0; --i) tem = (tem * 2) + bit(x, i); tem = bin[pos] - tem; gpos = pos; return x+tem; } inline void sol2() { L = getll(), R = getll(); if(L == 0 && R == 0) { puts("1"); return ; } L = max(L, 1ll); for (int i=0; i<=62; ++i) hv[i] = 0; int nL = 0; for (int i=62; i; --i) if(bin[i] > L && bin[i-1] <= L) nL = i; ll cur = L, tem; hv[nL - 1] = 1; while((tem = gnext(cur)) <= R) { cur = tem; hv[gpos] = 1; // printf("%I64d\\n", cur); // system("pause"); } int times = 0; for (int i=0; i<=62; ++i) times += hv[i]; cout << bin[times] << endl; } int main() { freopen("manger.in", "r", stdin); freopen("manger.out", "w", stdout); bin[0] = 1; for (int i=1; i<=62; ++i) bin[i] = bin[i-1] * 2; int T; cin >> T; while(T--) sol2(); return 0; } /* e.g 23333 66666 101101100100101 . 101101100100110 . +1 101101100100111 . +1 101101100101000 . +1 101101100101100 . +4 101101100110000 . +4 101101101000000 . +16 101101101100000 . +32 101101110000000 . +32 */
以上是关于雅礼集训1.2 T1串的主要内容,如果未能解决你的问题,请参考以下文章