P10877「KDOI-07」n1gr tS0i 题解
「KDOI-07」n1gr tS0i 题解
诈骗题,采用一个先猜后证的方法。
思路
先说赛时思路,不难发现每个询问的答案与 01 串本身是什么样子没有半毛钱关系,然后发现题目不给第二组数据的解释,猜测答案可能很简单,而注意到
对于小数据特殊情况,我们考虑写个暴力 dfs,发现只有
回来考虑一下为什么
我们考虑相邻的两个数的情况,由于我们已知 01 串本身不会影响答案个数,所以我们用
详细操作如下:假设某 01 串的部分为
- 变为
00 :进行操作[1,2],[1,2] ,改完得到(00)00 。 - 变为
11 :进行操作[1,4],[3,4] ,改完得到(11)00 。 - 变为
10 :进行操作[1,3],[2,3] ,改完得到(10)00 。 - 变为
01 :进行操作[2,4],[3,4] ,改完得到(01)00 。
由于这种操作具有对称性,所以当最后不足两个数的时候可以转到前面,这样,在
反观操作的那部分,不难发现 01 串长度至少为
代码
我是蒟蒻,入门题想半天。
#include <iostream>
#include <algorithm>
#define ll long long
using namespace std;
const ll N=1e5+10;
const ll MOD=998244353;
inline ll read(){
register ll f=1,x=0;
register char c=getchar();
while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
return x*f;
}
ll T,n;
char s[N];
//当然这题不用快速幂也能过
ll ksm(ll a,ll b){
ll ret=1;
while(b){
if(b&1) ret=ret*a%MOD;
a=a*a%MOD;
b>>=1;
}
return ret;
}
int main(){
T=read();
while(T--){
n=read();
scanf("%s",s+1);
if(n<=3){
if(n==2) printf("1\n");
if(n==3) printf("4\n");
}
else printf("%lld\n",ksm(2,n));
}
return 0;
}