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; }
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; }
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; }
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; }