复活小结—水题三连

宣布复活有一段时间了,CSP一轮都过去了,学了软件工程,借着C语言课的机会写了好多水题,现在恢复到普及水平了吧。。。

写几道水题题解,做个记录

NO.1 宝石串(前缀和)

https://www.luogu.org/problem/P2697

题目大意:给定一个由‘G’‘R’组成的字符串,求一段最长的区间,是‘G’‘R’数量相等

数据范围:字符串长度<=1000000

解法:‘G’视为-1,‘R’视为1,求前缀和,前缀和相同的两个位置之间的字符串符合要求,用记录各前缀和位置的方法能线性求最大值

#include<cstdio>
#include<cstring>
char s[1000005];
int ans,a[1000005],sl[2000005][2];
int max(int x,int y)
{
    return x>y?x:y;
}
int main()
{
    scanf("%s",s);
    int len=strlen(s);
    if(s[0]=='R') a[0]=1;
    else a[0]=-1;
    for(int i=1;i<len;i++)
    {
        if(s[i]=='R') a[i]=a[i-1]+1;
        else a[i]=a[i-1]-1;
        if(a[i]==0) ans=i+1;
    }
    for(int i=0;i<len;i++)
    {
        int w=a[i]+len;
        if(sl[w][0]==0) sl[w][0]=i+1;
        else sl[w][1]=i+1;
    }
    int m=2*len+1;
    for(int i=0;i<=m;i++)
    {
        ans=max(ans,sl[i][1]-sl[i][0]);
    }
    printf("%d",ans);
    return 0;
}

NO.2 

[USACO18FEB]Rest Stops(排序+贪心)

https://www.luogu.org/problem/P4266

题目大意:给出路的长度L,休息站的个数,以及john和bessie走一米需要的秒数

给出休息站的位置和停留一秒获得的美味值。Bessie可以再休息站停留。每停留一秒就能得到这个站的美味值,但是Bessie必须一直在John前面

数据范围:n<=100000,走一米需要的秒数<=100000(结果可能爆int)

解法:按照每个站的美味值排序,让Bessie在美味值最高的休息站上尽可能多地停留,直到John追上来,然后在剩下的休息站里再选择美味值最大的。

#include<cstdio>
#include<algorithm>
using namespace std;
void read(int &y)
{
    y=0;char x=getchar();
    while(x<'0'||x>'9') x=getchar();
    while(x>='0'&&x<='9')
    {
        y=y*10+x-'0';
        x=getchar();
    }
}
struct pos
{
    int x,v;
}a[100005];
bool cmp(pos x,pos y)
{
    if(x.v>y.v) return 1;
    if(x.v==y.v&&x.x<y.x) return 1;
    return 0;
}
int l,n,rf,rb,tx;
long long tans,ans;
int main()
{
//    freopen("testdata.in","r",stdin);
    read(l);read(n);read(rf);read(rb);
    for(int i=0;i<n;i++)
    {
        read(a[i].x);read(a[i].v);
    }
    sort(a,a+n,cmp);
//    for(int i=0;i<n;i++) printf("%d %d\n",a[i].x,a[i].v);
    for(int i=0;i<n;i++)
    {
        if(a[i].x>tx)
        {
            tans=(a[i].x-tx);
            tans*=(rf-rb);
            ans+=tans*a[i].v;
            tx=a[i].x;
        }
    }
    printf("%lld",ans);
    return 0;
}

NO.3 细胞分裂

https://www.luogu.org/problem/P1069

题目大意:给出n个数s[i],和m1,m2

求最小的x,使pow(s[i],x)能整除pow(m1,m2)

数据范围:1N10000,1m130000,1m210000,1≤si2,000,000,000

解法:将m1因数分解,并把每个因数的数量乘m2

然后将每个si因数分解,如果存在m1有,但si没有的因数,那么这个si就不能满足要求

否则这个si的对应的x满足si,每个因数乘x之后,每个因数的数量大于m1

最终答案为所有满足题意的x中最小的一个

#include<cstdio>
#include<cstring>
using namespace std;
void read(int &y)
{
    y=0;char x=getchar();
    while(x<'0'||x>'9') x=getchar();
    while(x>='0'&&x<='9')
    {
        y=y*10+x-'0';
        x=getchar();
    }
}
int n,m1,m2,tx,ans=2147483647,maxi;
int a[30005],b[30005];
int min(int x,int y)
{
    return x<y?x:y;
}
int max(int x,int y)
{
    return x>y?x:y;
}
int main()
{
//    freopen("testdata1.txt","r",stdin);
    read(n);
    read(m1);read(m2);
    for(int i=2;i<=m1;i++)
    {
        while(m1%i==0)
        {
            m1/=i;
            a[i]++;
        }
        a[i]*=m2;
        if(a[i]) maxi=i;
    }
//    for(int i=1;i<=maxi;i++) printf("%d %d\n",i,a[i]);
//    return 0;
    for(int i=1;i<=n;i++)
    {
        read(tx);
        int tans=0;
        memset(b,0,sizeof(b));
        for(int j=2;j<=tx;j++)
        {
            while(tx%j==0)
            {
                tx/=j;
                b[j]++;
            }
            if(j>maxi) break;
        }
        for(int j=2;j<=maxi;j++)
        {
            if(a[j]&&b[j])
            {
                if(a[j]%b[j]==0) tans=max(tans,a[j]/b[j]);
                else tans=max(tans,a[j]/b[j]+1);
            }
            if(a[j]&&b[j]==0)
            {
                tans=2147483647;
                break;
            }
        }
        ans=min(tans,ans);
    }
    if(ans==2147483647) printf("-1");
    else printf("%d",ans);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/zeroform/p/11765158.html