牛客小白月赛91VP

1.签到:https://ac.nowcoder.com/acm/contest/78807/A

AC代码:

#include<bits/stdc++.h>
using namespace std;
string a[10];
int main()
{
    for(int i=0;i<6;i++) cin>>a[i];
    if(a[0][3]=='.') cout<<'o';
    else if(a[4][5]=='\\') cout<<'m';
    else cout<<'p';
}

2.简单的博弈:https://ac.nowcoder.com/acm/contest/78807/B

AC代码:

#include<bits/stdc++.h>
using namespace std;
int t,n;
int main()
{
    cin>>t;
    while(t--)
    {
        cin>>n;
        if(n%4==0) cout<<"Bong"<<endl;
        else cout<<"Bing"<<endl;
    }
}

3.贪心:https://ac.nowcoder.com/acm/contest/78807/C

显然,假如它到中心的时间>两边坍塌的max时间一定没有希望。

我们假设一边坍塌要m时间,另一边n(m>n)

一开始在m那一边走到终点要t1(t1<=m),在n走到终点要t2(t2<=n),那么t1+t2<=m;

我们先让n边走t2,此时m那一边坍塌了t2,即m-t2,又m-t2>=t1,因此我们可以再直接走到终点。

下面是AC代码:

#include<bits/stdc++.h>
using namespace std;
int n,m,k;
int main()
{
    cin>>n>>m>>k;
    int v1=n/2+1,v2=m/2+1;
    int c1=n/2,c2=m/2;
    int cnt=0;
    while(k--)
    {
        int x,y;
        scanf("%d%d",&x,&y);
        int cx=abs(x-v1),cy=abs(y-v2);
        if(cx+cy<max(v1,v2)) cnt++;
    }
    cout<<cnt;
}

4.DP的思想:https://ac.nowcoder.com/acm/contest/78807/D

我们让cnt表示前面数的选取总方案,假如此位是偶数,那么以他结尾的贡献就是cnt+1(自己)

如果是奇数那么没有贡献。

对于cnt的变化都是2*cnt+1(0的话由于不能前导还要-1)

下面是AC代码:

#include<bits/stdc++.h>
using namespace std;
int n;
string s;
long long cnt=0,sum=0;
int mod=1e9+7;
int main()
{
    cin>>n>>s;
    for(int i=0;i<s.size();i++)
    {
        if(s[i]=='0')
        {
            sum=(sum+cnt+1)%mod;
            cnt=cnt*2%mod;
        }
        else if((s[i]-'0')%2)
        {
            cnt=(cnt*2+1)%mod;
        }
        else{
            sum=(sum+cnt+1)%mod;
            cnt=(cnt*2+1)%mod;
        }
    }
    cout<<sum;
}

5.子序列自动机:https://ac.nowcoder.com/acm/contest/78807/E

我们用nxt[i][j]表示从i开始后到第一个j出现的位置(不包含自己)

我们再找到第一个ACCEPT以及WA的位置相减即可。

下面是AC代码:

#include<bits/stdc++.h>
using namespace std;

int n,k;
string s;
int nxt[200010][30];//从i开始后到第一个j出现的位置(不包含自己)
int cnt=0;
string ss="ACCEPT";
string sss="WA";
int findac(int pos)
{
    if(s[pos]=='A')
    {
        for(int i=1;i<=5;i++)
        {
            pos=nxt[pos][ss[i]-'A'];
        }
    }
    else
    {
        for(int i=0;i<=5;i++)
        {
            pos=nxt[pos][ss[i]-'A'];
        }
    }
    return pos;
}
int findwa(int pos)
{
    if(s[pos]=='W')
    {
        for(int i=1;i<=1;i++)
        {
            pos=nxt[pos][sss[i]-'A'];
        }
    }
    else
    {
        for(int i=0;i<=1;i++)
        {
            pos=nxt[pos][sss[i]-'A'];
        }
    }
    return pos;
}
int main()
{
    cin>>n>>k;
    cin>>s;
    for(int i=0;i<=26;i++) nxt[s.size()-1][i]=n;
    for(int i=0;i<26;i++) nxt[n][i]=n;
    for(int i=s.size()-2;i>=0;i--)
    {
        for(int j=0;j<=25;j++)
        {
            if('A'+j==s[i+1])
            {
                nxt[i][j]=i+1;
            }
            else{
                nxt[i][j]=nxt[i+1][j];
            }
        }
    }
    //cout<<findwa(1);
    for(int i=0;i<s.size();i++)
    {
        int j1=findac(i);
        int j2=findwa(i);
        cnt+=max(0,j2-j1-max(0,k-6));
    }
    //for(int i=0;i<=s.size()-1;i++) cout<<nxt[i][0]<<" ";
    cout<<cnt;
}

6.贡献法+拆位:https://ac.nowcoder.com/acm/contest/78807/F

直接贡献法枚举(i,j)复杂度n^2级别,看到异或我们就直接拆位,考虑到其大小我们枚举1--20,对于每一位t,我们考虑它的贡献,假如他是1,那么我们只考虑它前面的贡献,也就是为0的位置(组成一个(i,j)序对),至于它的大小就是2^t*(n-i+1)*v0,v0就是前面0的下标的前缀和,而它后面可以有n-i+1中选择。而对于(i,j),因为还要考虑对后面的贡献,也就再来一份。

下面是AC代码:

#include<bits/stdc++.h>
using namespace std;
int n;
long long a[1000100];
int mod=1e9+7;
int main()
{
    cin>>n;
    for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
    long long ans=0;
    for(int i=0;i<=20;i++)
    {
        long long v0=0,v1=0;
        for(int j=1;j<=n;j++)
        {
            if((a[j]>>i)&1)
            {
                ans=(ans+v0*(n-j+1)%mod*(1<<i)%mod*2% mod)%mod;
                v1=(v1+j)%mod;
            }
            else{
                ans=(ans+v1*(n-j+1)%mod*(1<<i)%mod*2% mod)%mod;
                v0=(v0+j)%mod;
            }
        }
    }
    cout<<ans;
}

  • 15
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值