牛客练习赛79 总结

A 炼金术师

离散化一下排个序取最值即可

#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
const int N=1e6+10;
int a[N],x[N],y[N],n,m,ans;

int main() {
    scanf("%d",&n);
    if (n==0) return printf("0"),0;
    for (int i=1;i<=n;i++) scanf("%d",&x[i]),y[i]=x[i];
    sort(x+1,x+n+1);m=unique(x+1,x+n+1)-x-1;
    for (int i=1,j;i<=n;i++) a[j=lower_bound(x+1,x+m+1,y[i])-x]=max(a[j],i);
    for (int i=m;i;i--) a[i]=max(a[i],a[i+1]);
    ans=1;for (int i=1;i<m;i++) if (a[i]!=a[i+1]) ans++;
    printf("%d\n",ans);
}
View Code

B 刀工对决

各自除掉最大公因数以后如果仍存在非 3,5 的因数则必不行

然后分类讨论,如果剩下因子的 3 和 5 分别在不同数上, 则考虑若 3 的个数大于 5 ,则只需要消耗 3 的个数刀( 5 变成 3 ,3 减到 5 的个数)

若 3 的个数小于 5 ,则需要 5 的个数+ 5的个数 - 3 的个数

如果在同一个数上就是 5 的个数*2 + 3 的个数

#include <iostream>
#include <cstdio>
using namespace std;
int n,a,b,gcd,ans,ta,tb,fa,fb;

int GCD(int a,int b) {return !a?b:GCD(b%a,a);}

int main() {
    for (scanf("%d",&n);n;n--) {
        scanf("%d%d",&a,&b);gcd=GCD(a,b);ta=tb=fa=fb=0;a/=gcd;b/=gcd;
        while (a>1) {
            if (a%3==0) {a/=3,ta++;continue;}
            if (a%5==0) {a/=5,fa++;continue;}
            return printf("-1"),0;
        }
        while (b>1) {
            if (b%3==0) {b/=3,tb++;continue;}
            if (b%5==0) {b/=5,fb++;continue;}
            return printf("-1"),0;
        }
        if (fa<fb) swap(ta,tb),swap(fa,fb);
        if (tb-ta>=fa-fb) ans+=tb-ta;
        else ans+=(fa-fb)*2+ta-tb;
    }
    printf("%d\n",ans);
}
View Code

C 小G的GCD

不知道怎么A的,乱搞了个结论,不会证

#include <iostream>
#include <cstdio>
#include <cmath>
using namespace std;
typedef long long ll;
ll n,a,b,ans;

int main() {
    scanf("%lld",&n);a=b=1;
    if (n==1) return printf("2"),0;
    while (a<=n) {
        if (a>b) swap(a,b);
        a+=b;ans++;
    }
    printf("%lld",ans+1);
}
View Code

D 回文字D

马拉车搞一下,然后讨论 d 的奇偶性,有显然的 DP

一开始在马拉车的双倍字符串上搞得太复杂了,罚了好多时

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int N=1e7+10;
int p[2*N],n,m,d,f[N];
char s[N],t[2*N];

void Manacher() {
    int rig=0,i=0;p[0]=1;
    for (int j=1;j<=m;j++) {
        if (rig<j) p[j]=1; else p[j]=min(p[2*i-j],rig-j+1);
        while (t[j+p[j]]==t[j-p[j]]) p[j]++;
        if (j+p[j]-1>rig) rig=j+p[j]-1,i=j;
    }
}
 
int main() {
    scanf("%d%d",&n,&d);
    if (d>n) return printf("1"),0;
    scanf("%s",s+1);
    t[0]='$';for (int i=1;i<=n;i++) t[++m]='#',t[++m]=s[i];
    t[++m]='#';t[++m]='@';
    Manacher();
    for (int i=1;i<d;i++) f[i]=1;
    for (int i=d;i<=n;i++) {
        f[i]=2147483647;
        if (p[2*(i-d/2)+(d%2==0)]>d) f[i]=min(p[2*(i-d/2-1)+(d%2==0)]>d?f[i-1]:n+1,f[i-d]+1);
        f[i]=min(f[i],f[i-d+1]+1);
    }
    printf("%d",f[n]);
}
View Code

 

posted @ 2021-03-29 21:15  Vagari  阅读(42)  评论(0编辑  收藏  举报