iwtgm-26

发布时间 2023-11-24 11:56:43作者: WW爆米花

题目链接

A.

拿例子说话
n1,那么在1处建信号站,信号为0
n
2,那么在1和2处建信号站,信号均为0
n3,可以在1,2,3处建信号为0的信号站,也可以在2处建信号为1的信号站
n
4,可以在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;
}