首页 > 代码库 > noip2013 普及组

noip2013 普及组

T1 记数问题 题目传送门

这道题就是一道暴力咯 其实感觉数据大点一个应该是道数位dp了 不过还是懒所以写了暴力

技术分享
#include<cstdio>
#include<cstring>
#include<algorithm>
#define LL long long
using namespace std;
int read(){
    int ans=0,f=1,c=getchar();
    while(c<0||c>9){if(c==-) f=-1; c=getchar();}
    while(c>=0&&c<=9){ans=ans*10+(c-0); c=getchar();}
    return ans*f;
}
int n,x,ans;
int main()
{
    n=read(); x=read();
    for(int i=1;i<=n;i++){
        int k=i;
        while(k){
            if(k%10==x) ans++;
            k=k/10;
        }
    }
    printf("%d\n",ans);
    return 0;
} 
View Code

T2 表达式求值  题目传送门 

乘法优先级比加法高 所以先处理一波乘法 然后全部加起来就好了哇 2333

技术分享
#include<cstdio>
#include<cstring>
#include<algorithm>
#define LL long long
using namespace std;
const int mod=10000;
char s[5000007],last;
LL ans,sum,w[500007],top,len;
int main()
{
    scanf("%s",s+1); len=strlen(s+1);
    for(int i=1;i<=len;i++){
        if(s[i]>=0&&s[i]<=9) sum=sum*10+(s[i]-0);
        if(s[i]<0||s[i]>9||i==len){
            //printf("%lld\n",sum);
            sum=sum%mod;
            if(!top) w[++top]=sum;
            else{
                if(last==+) w[++top]=sum;
                else w[top]=w[top]*sum%mod;
            }
            sum=0; last=s[i];
        }
    }
    for(int i=1;i<=top;i++) ans=(ans+w[i])%mod; //printf("%lld\n",w[i]);
    printf("%lld\n",ans);
    return 0;
} 
View Code

T3 小朋友的数字 题目传送门

首先读题可得 应该先处理一波最大子串 然后累加处理答案 

当然如果只是累加 而中途没有%mod 最后两个点过不了 因为会炸longlong 

观察我们可以知道除了第一个点 后面点的分数是不会下降的 所以我们可以判一波中途有没有点超过mod

又由题可得第一个点是不会超过的 所以如果中途有点超过 那么答案就一定是最后一个小朋友的分数 不然就是第一个和最后一个的最大值

技术分享
#include<cstdio>
#include<cstring>
#include<algorithm>
#define LL long long
#define maxx 1000000000
using namespace std;
const int M=1500007;
LL read(){
    LL ans=0,f=1,c=getchar();
    while(c<0||c>9){if(c==-) f=-1; c=getchar();}
    while(c>=0&&c<=9){ans=ans*10+(c-0); c=getchar();}
    return ans*f;
}
LL n,mod;
LL w[M],sum[M],mx[M],ans;
bool f;
int main()
{
    n=read(); mod=read();
    for(int i=1;i<=n;i++) w[i]=read();
    mx[1]=w[1]; 
    LL tot=0,mx1=-0x7fffffff;
    for(int i=1;i<=n;i++){
        tot+=w[i]; mx1=max(mx1,tot);
        mx[i]=mx1;
        if(tot<0) tot=0;
    }
//    for(int i=1;i<=n;i++) printf("%lld ",mx[i]); printf("\n");
    sum[1]=mx[1]; ans=sum[1]+mx[1];
    for(int i=2;i<=n;i++){
        sum[i]=ans;
        if(sum[i]+mx[i]>ans) ans=sum[i]+mx[i];
        if(ans>=maxx) ans=ans%mod,f=1;
    }
    if(!f) ans=max(sum[1],sum[n]);
    else ans=sum[n];
    printf("%lld\n",ans%mod);
    return 0;
} 
View Code

T4 车站分级 题目传送门  

这道题我解决的方法是拓扑排序 每次将未停留的点指向停留的点 表示未停留的点比停留的点等级低 然后就是一波拓排解决问题咯

技术分享
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int M=3507;
int read(){
    int ans=0,f=1,c=getchar();
    while(c<0||c>9){if(c==-) f=-1; c=getchar();}
    while(c>=0&&c<=9){ans=ans*10+(c-0); c=getchar();}
    return ans*f;
}
int f[M][M],cnt;
int in[M],x,n,m,v,sum[M];
int head,tail,ans=1,q[M],num[M];
int main()
{
    n=read(); m=read();
    while(m--){
        v=read(); cnt++;
        for(int i=1;i<=v;i++) q[i]=read(),sum[q[i]]=cnt;
        for(int i=q[1];i<=q[v];i++)if(sum[i]!=cnt){
            for(int k=1;k<=v;k++) 
             if(!f[i][q[k]]) f[i][q[k]]=1,in[q[k]]++;
        }
    }
    for(int i=1;i<=n;i++) if(!in[i]) q[tail++]=i,num[i]++;
    while(head!=tail){
        int x=q[head++]; if(head>M) head=0;
        for(int i=1;i<=n;i++) if(f[x][i]){
            in[i]--;
            if(!in[i]) {q[tail++]=i; num[i]=num[x]+1;}
        }
    }
    for(int i=1;i<=n;i++) ans=max(ans,num[i]);
    printf("%d\n",ans);
    return 0;
}
View Code

 

noip2013 普及组