牛客小白月赛13 ABCD题解

比赛链接:

https://ac.nowcoder.com/acm/contest/549#question

A 小A的签到题

 打表找规律,如果是偶数输出-1,如果是偶数输出1.

代码如下:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
struct mat
{
    ll m[5][5];
};
mat a,b,c;
mat mul(mat a,mat b)
{
    memset (c.m,0,sizeof(c.m));
    for (int i=0;i<2;i++)
    {
        for (int j=0;j<2;j++)
        {
            for (int k=0;k<2;k++)
            {
                c.m[i][j]+=a.m[i][k]*b.m[k][j];
            }
        }
    }
    return c;
}
mat pow (mat a,ll n)
{
    mat b;
    b.m[0][0]=1,b.m[1][0]=1;
    b.m[1][0]=1,b.m[1][1]=1;
    while(n)
    {
        if(n%2) b=mul(a,b);
        a=mul(a,a);
        n>>=1;
    }
    return b;
}
int main() {
    ll n;
    scanf("%lld",&n);
    printf("%d\n",n%2==0? -1:1);
    return 0;
}
B 小A的回文串

 暴力,分别求出奇数回文串和偶数回文串最大的情况。

代码如下:

#include <bits/stdc++.h>
using namespace std;
const int maxn=5*1e3+5;
char s[maxn];
int main()
{
    scanf("%s",s);
    int len=strlen(s);
    int ans=0;
    for (int i=0;i<len;i++)
    {
        int tlen=0;
        while(tlen*2+1<=len&&s[(i+tlen+len)%len]==s[(i-tlen+len)%len]) tlen++;
        ans=max(tlen*2-1,ans);
    }
    for (int i=0;i<len;i++)
    {
        int tlen=0;
        if(s[i]==s[(i-1+len)%len])
        {
            while((tlen+1)*2<=len&&s[(i+tlen+len)%len]==s[(i-tlen-1+len)%len]) tlen++;
            ans=max(ans,(tlen)*2);
        }
    }
    printf("%d\n",ans);
    return 0;
}
C 小A买彩票

 递推,类似于背包,dp[i][j]表示买i张彩票获得j元的方法数。

打个表存一下,然后输出即可。

代码如下:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=35;
ll ans;
ll a[50];
ll dp[35][125];
ll ansc[35];
ll ansp[35];
ll gcd (ll a,ll b)
{
    return b==0? a:gcd(b,a%b);
}
int main()
{
    ansc[0]=ansp[0]=1;
    a[0]=1;
    for (int i=1;i<=30;i++) a[i]=a[i-1]*4;
    memset (dp,0,sizeof(dp));
    dp[1][1]=dp[1][2]=dp[1][3]=dp[1][4]=1;
    for (int i=2;i<=30;i++)
    {
        for (int j=1;j<=120;j++)
        {
            if(dp[i-1][j])
            {
                for (int k=1;k<=4;k++)
                {
                    dp[i][j+k]+=dp[i-1][j];
                }
            }
        }
    }
    for (int i=1;i<=30;i++)
    {
        ll ans=0;
        for (int j=120;j>=3*i;j--)
        {
            ans+=dp[i][j];
        }
        ll G=gcd(ans,a[i]);
        ansc[i]=ans/G,ansp[i]=a[i]/G;
    }
    int n;
    scanf("%d",&n);
    printf("%lld/%lld\n",ansc[n],ansp[n]);
    return 0;
}
D 小A的位运算

 维护前缀和和后缀和,然后求i-1的前缀或和i+1的后缀或或起来即可。

代码如下:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=5*1e6+5;
int n;
ll a[maxn];
ll h[maxn];
ll t[maxn];
ll ans;
int main()
{
    ans=0;
    h[0]=0;
    scanf("%d",&n);
    t[n+1]=0;
    for (int i=1;i<=n;i++)
    {
        scanf("%lld",&a[i]);
        h[i]=h[i-1]|a[i];
    }
    for (int i=n;i>=1;i--)
    {
        t[i]=t[i+1]|a[i];
    }
    for (int i=1;i<=n;i++)
    {
        ans=max(ans,h[i-1]|t[i+1]);
    }
    printf("%lld\n",ans);
    
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_41410799/article/details/89294580