这场D被切穿了。
A题
答案为
x 或者 x-1 1
B题
答案就是最长的连续一段的长度+1
证明的话大概可以将它看成是几段连续上升和下降的段,然后在峰谷、峰顶分别填上最小、最大,剩下的就依次递增或递减就行。
C题
将一段连续的0/1视作一个块,那么我们最小化这个块的数量就行。
D题如果猜到如果有解那么ans<=2,就变得非常简单。
E题
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<map>
#include<vector>
#define A puts("YES")
#define B puts("NO")
#define fo(i,a,b) for (ll (i)=(a);(i)<=(b);(i)++)
#define fd(i,b,a) for (int (i)=(b);(i)>=(a);(i)--)
#define mk(x,y) make_pair((x),(y))
using namespace std;
typedef double db;
typedef long long ll;
const int N=1e6+5;
const ll mo=998244353;
ll n,a[N],k,c[N],b[N],d[N];
vector<ll> v;
ll f[N],ans,size,tot,res;
int main()
{
// freopen("data.in","r",stdin);
scanf("%lld",&k);
n=1<<k;
fo(i,1,n){
a[i]=-1;
}
fo(i,1,n) {
scanf("%lld",&d[i]);
a[d[i]]=i;
}
f[0]=1;
b[0]=1;
fo(i,1,n) {
f[i]=f[i-1]*i%mo;
b[i]=b[i-1]*2ll%mo;
}
if (a[1]!=-1) v.emplace_back(a[1]),res++;
ans=1;
fo(j,0,k-1) {
fo(i,b[j]+1,b[j+1]) {
if (a[i]!=-1) {
v.emplace_back(a[i]);
tot++;
}
}
size=n/b[j+1];
fo(i,1,b[j+1]) c[i]=0;
for (auto i:v) {
if (i%size==0) c[i/size]++;
else c[i/size+1]++;
}
fo(i,1,b[j+1]) if (c[i]>1) ans=0;
ll z=0;
fo(i,1,b[j+1]) {
if (i&1) {
if (c[i] && c[i+1]) z++;
}
}
ans=ans*f[b[j]-tot]%mo*b[ b[j]-(tot+res-z)]%mo;
res+=tot;
tot=0;
}
fo(i,1,n) {
if (i&1) {
if (d[i]>n/2 && d[i+1]>n/2) ans=0;
}
}
printf("%lld",ans);
return 0;
}
标签:Educational,Rated,ll,Codeforces,tot,fo,ans,include,define
From: https://www.cnblogs.com/ganking/p/17778486.html