iwtgm-26
A.
拿例子说话
n1,那么在1处建信号站,信号为0
n2,那么在1和2处建信号站,信号均为0
n3,可以在1,2,3处建信号为0的信号站,也可以在2处建信号为1的信号站
n4,可以在1,2,3,4处建信号为0的信号站,也可以在2处建信号为1的信号站并在4处建信号为0的信号站,还可以在3处建信号为1的信号站,在1处建信号为0的信号站
总结:在一个地方建信号站,它所能覆盖的范围一定是奇数个
然后写几个例子后发现这样居然满足斐波拉契数列,那么代码就很好写了
ll n;
ll a[N],b[N];
ll mod=998244353;
ll ans;
ll ksm(ll x,ll y,ll p){
ll res=1;
while(y>0){
if(y&1)res=res*x%p;
x=x*x%p;
y/=2;
}
return res%p;
}
void solve() {
cin>>n;
ans=ksm(2,n,mod);
a[1]=1;a[2]=1;
for(int i=3;i<=n;i++){
a[i]=a[i-1]+a[i-2];
a[i]%=mod;
}
cout<<a[n]*ksm(ans,mod-2,mod)%mod;
}
B.
这个思路比较好出,注重在如何简单地实现代码
简单来说,就是连续的非降序的几个数可以在同一层
int n,a[N];
void solve() {
cin>>n;
for(int i=1;i<=n;i++)cin>>a[i];
if(n==1){
cout<<0<<endl;return ;
}
if(n==2){
cout<<1<<endl;return ;
}
int last=1,now=1,ans=0,k=1;
for(int i=2;i<n;i++){
if(a[i]<a[i+1])++now;
else{
if(k==last)++ans;
--last;
if(last==0){
k=last=now;now=1;
}
else ++now;
}
}
if(now){
if(k==last)++ans;
--last;
}
cout<<ans<<endl;
}
C.
思路较为好出,注重简单实现代码
先比较哪种操作更划算
对于要消去的一段,火球术的限制是少于k个的不能用该操作,狂暴的限制是若存在数比两端的数大,那么这个数无法消除
int n,m,x,k,y,ans;
int pos[200010],a[200010],b[200010];
bool check()
{
int l=0,tot=0;
for(int i=1;i<=m;i++)
{
while(a[l]!=b[i])
{
l++;
if(l>n)
return 0;
}
if(a[l]==b[i])
{
pos[l]=1;
tot++;
}
}
return tot==m;
}
signed main()
{
cin>>n>>m>>x>>k>>y;
for(int i=1;i<=n;i++)
{
cin>>a[i];
}
for(int i=1;i<=m;i++)
{
cin>>b[i];
}
if(!check())
{
puts("-1");
return 0;
}
pos[n+1]=1;
int last=0,maxn=0;
for(int i=1;i<=n+1;i++)
{
if(pos[i]==1)
{
int len=i-last-1;//块长
if(len<k)//块长<k,只能使用y魔法
{
if(maxn>max(a[last],a[i]))
{
puts("-1");
return 0;
}
else
{
ans+=len*y;
maxn=0;
}
}
else//块长大于等于k
{
if(x>y*k)//y魔法更划算
{
if(maxn>max(a[last],a[i]))
{
ans+=(len-k)*y+x;//最后k个用x消灭
}
else
{
ans+=len*y;
}
}
else//x魔法更划算
{
ans+=(len%k)*y+((len-len%k)/k*x);
}
}
maxn=0;
last=i;//更新last的位置
}
else//更新块中要消灭的数的最大值
{
maxn=max(maxn,a[i]);
}
}
cout<<ans;
return 0;
}