CodeForces,  ICPC/ACM

Educational Codeforces Round 94

A – String Similarity

题意

如果有两个字符串,若他们存在有相同的以为,那么我们称这两个字符串是相似的。

给定一个长度为$2n-1$的字符串$S$,要求构造出一个字符串使得长度为$n$的$S$的任意子串都与该字符串相似。

解题思路

长度为$2n-1$的字符串它的长度为$n$的子串数量刚好是$n$,所以我们考虑使得每个子串都影响到答案的一位。

我的构造思路是令$ans_i=s_{2i}^{}$

参考代码

#include <bits/stdc++.h>
#define rep(i,a,n) for (int i=a;i<n;i++)
using namespace std;
const int MAXN=(int)1e5+5;
char buf[MAXN];
int main()
{
    int T,n;
    cin>>T;
    while (T--)
    {
        cin>>n>>buf;
        rep(i,0,n)cout<<buf[i*2];
        cout<<endl;
    }
    return 0;
}

B – RPG Protagonist

题意

$p$和$f$分别代表你和你的同伴的背包的容量值
$cnt_s$和$cnt_w$分别代表$s$物品的数量和$w$物品的数量
$s$和$w$分别代表这两件物品的体积
求两个人一共能携带的物品的最大值是多少

解题思路

我本来考虑是否有$O(1)$的贪心思路的,但是那些看似没有问题的贪心思路都是有问题的。

正确的思路是枚举一个人的$s$的物品的数量,然后剩下的贪心解决,此处的$s<w$如果不是交换就好了。

时间复杂度为$O(cnt_s)$

参考代码

#include <bits/stdc++.h>
#define rep(i,a,n) for (int i=a;i<n;i++)
typedef long long ll;
using namespace std;

int main()
{
    int T;
    int p,f;
    int cs,cw;
    int s,w;
    cin>>T;
    while(T--)
    {
        cin>>p>>f;
        cin>>cs>>cw;
        cin>>s>>w;
        if(s>w){swap(s,w);swap(cs,cw);}
        int ans=0;
        rep(i,0,cs+1)
        {
            if(i*s>p)break;
            int tmp=i;
            int k=min(cw,(p-i*s)/w);
            tmp+=k;
            int j=min(cs-i,f/s);
            tmp+=j;
            tmp+=min(cw-k,(f-s*j)/w);
            ans=max(ans,tmp);
        }
        cout<<ans<<endl;
    }
    return 0;
}

C – Binary String Reconstruction

题意

给定一个长度为$n$的由0和1构成的字符串$w$,和一个整数$x$。

字符串$w$和字符串$s$存在这如下的变换

  • 如果$w_{i+x}^{}=1$那么$s_i=1$
  • 如果$w_{i-x}^{}=1$那么$s_i=1$
  • 否者就为0

已知字符串$s$和$n$求字符串$w$

解题思路

我们可以从字符串$s$中的0来推测出字符串$w$中的0的位置。
然后我们还需要检验一下生成的字符串是否是答案。

时间复杂度为$O(n)$

PS:我发现有些时候用离散数学化简条件真的爽

参考代码

#include <bits/stdc++.h>
#define MEM(a,b) memset((a),(b),sizeof(a))
#define rep(i,a,n) for (int i=a;i<n;i++)
using namespace std;
const int MAXN=(int)1e5+5;
char buf[MAXN];
int n,x;
bool ans[MAXN];
bool check()
{
    rep(i,0,n)if(buf[i]=='1'&&(i-x<0||ans[i-x])&&(i+x>=n||ans[i+x]))return false;
    return true;
}
int main()
{
    int T;
    cin>>T;
    while(T--)
    {
        cin>>buf;
        cin>>x;
        n=strlen(buf);
        MEM(ans,0);
        for (int i = 0; i < n; i++)
        {
            if(buf[i]=='0')
            {
                if(i+x<n)ans[i+x]=true;
                if(i-x>=0)ans[i-x]=true;
            }
        }
        if(check())rep(i,0,n){if(ans[i])cout<<'0';else cout<<'1';}
        else cout<<-1;
        cout<<endl;
    }
    return 0;
}

D – Zigzags

题意

给定一个长度为$n$的数组$a_n$。求有多少组$i,j,k,l$满足

  • $1\le i<j<k<l \le n$
  • $a_i=a_k$且$a_j=a_l$

解题思路

我们可以枚举$j$和$k$,然后统计$k$之后有多少个与$a_j$相同的数,$j$之前有多少个与$a_k$相同的数,然后乘起来就好了。

参考代码

#include <bits/stdc++.h>
#define rep(i,a,n) for (int i=a;i<n;i++)
typedef long long ll;
using namespace std;
const int MAXN=(int)3e3+5;
ll f[MAXN][MAXN];
int a[MAXN];
int main()
{
    int T,n;
    cin>>T;
    while(T--)
    {
        cin>>n;
        rep(i,1,n+1)cin>>a[i];
        rep(i,1,n+1)
        {
            memcpy(f[i],f[i-1],sizeof(f[i]));
            f[i][a[i]]++;
        }
        ll ans=0;
        rep(i,1,n+1)rep(j,i+1,n+1)ans+=f[i-1][a[j]]*(f[n][a[i]]-f[j][a[i]]);
        cout<<ans<<endl;
    }
    return 0;
}
Subscribe
提醒
guest
0 评论
Inline Feedbacks
View all comments
0
喜欢聆听每一种不同的观点,欢迎评论。x
()
x