首页 > 代码库 > Noip2007提高组总结
Noip2007提高组总结
两道基础题,后两题比较麻烦,算法想出来后,还是一些细枝末节的问题,需要特别注意,感觉Noip的题目质量还是挺高的,每做一套,都感觉会有大大小小不同的收获,就要月考了,最后把07年的题目总结一下,算是这两天的收获……
T1:统计数字
没有任何悬念的练习题,排序然后输出……
+ View Code?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | #include <cstdio> #include <algorithm> int n,a[200005],pos; using namespace std; int main(){ scanf ( "%d" ,&n); for ( int i=0;i<n;i++) scanf ( "%d" ,&a[i]); sort(a,a+n); pos=0; printf ( "%d " ,a[0]); for ( int i=1;i<=n;i++) if (a[i]!=a[i-1]){ printf ( "%d\n" ,i-pos),pos=i; if (a[i]) printf ( "%d " ,a[i]); } return 0; } |
T2:字符串的展开
字符串处理的基础题,主要考察读题的仔细程度和编程的素质,尽量代码短一些,那么也好调试一点。
+ View Code?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | #include <cstdio> #include <cstring> using namespace std; #define rep() for(int j=0;j<p2;j++) char s[1000000]; int p1,p2,p3; void pr1( int b, int e){ for ( int i=b;i<=e;i++)rep() printf ( "%c" ,( char )i);} void pr2( int b, int e){ for ( int i=e;i>=b;i--)rep() printf ( "%c" ,( char )i);} void pr3( int b, int e){ for ( int i=b;i<=e;i++)rep() printf ( "%c" , ‘*‘ );} int main(){ scanf ( "%d%d%d" ,&p1,&p2,&p3); scanf ( "%s" ,s); printf ( "%c" ,s[0]); for ( int i=1;i< strlen (s);i++){ if (s[i]!= ‘-‘ ){ printf ( "%c" ,s[i]); continue ;} if (p3==1){ if (s[i-1]>= ‘0‘ &&s[i+1]<= ‘9‘ &&s[i-1]<s[i+1]){ if (p1==3)pr3( int (s[i-1])+1, int (s[i+1])-1); else pr1( int (s[i-1])+1, int (s[i+1])-1); continue ; } if (s[i-1]>= ‘a‘ &&s[i+1]<= ‘z‘ &&s[i-1]<s[i+1]){ if (p1==1)pr1( int (s[i-1])+1, int (s[i+1])-1); else if (p1==2)pr1(s[i-1]- ‘a‘ + ‘A‘ +1,s[i+1]- ‘a‘ + ‘A‘ -1); else pr3( int (s[i-1])+1, int (s[i+1])-1); continue ; } } else { if (s[i-1]>= ‘0‘ &&s[i+1]<= ‘9‘ &&s[i-1]<s[i+1]){ if (p1==3)pr3( int (s[i-1])+1, int (s[i+1])-1); else pr2( int (s[i-1])+1, int (s[i+1])-1); continue ; } if (s[i-1]>= ‘a‘ &&s[i+1]<= ‘z‘ &&s[i-1]<s[i+1]){ if (p1==1)pr2( int (s[i-1])+1, int (s[i+1])-1); else if (p1==2)pr2(s[i-1]- ‘a‘ + ‘A‘ +1,s[i+1]- ‘a‘ + ‘A‘ -1); else pr3( int (s[i-1])+1, int (s[i+1])-1); continue ; } } printf ( "%c" ,s[i]); } return 0; } |
T3:矩阵取数游戏
这道题的Dp方程还是比较好推的,就是从中间向两端扩展,然后搜索进去层层外推即可,方程是f[i][j]=max{f[i][j-1]+a[j],f[i+1][j]+a[i]},然后是2的幂次问题,因为直接算幂的话比较慢,所以用霍纳规则,每一次出栈时乘2,就可以了,没打高精度60分:
+ View Code?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | #include <cstdio> #include <cstring> #include <iostream> using namespace std; typedef long long LL; LL ans,a[81],f[81][81]; LL getans( int s, int t){ if (f[s][t]) return f[s][t]; if (s==t) return f[s][s]=2*a[s]; LL t1,t2; t1=getans(s+1,t)+a[s]; t2=getans(s,t-1)+a[t]; if (t1>t2) return f[s][t]=2*t1; else return f[s][t]=2*t2; } int main(){ int n,m; scanf ( "%d%d" ,&n,&m); while (n--){ for ( int i=1;i<=m;i++) scanf ( "%d" ,&a[i]); memset (f,0, sizeof f); ans+=getans(1,m); } cout<<ans; return 0; } |
之后粘上高精度的,重载运算符版本……
+ View Code?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 | #include <cstdio> #include <cstring> #include <iostream> using namespace std; typedef struct bigint{ int le,u[81]; bigint(){le=0; memset (u,0, sizeof (u));} bigint operator+( const bigint &a){ int l=max(le,a.le); bigint m; for ( int i=0;i<=l;i++){ m.u[i]+=u[i]+a.u[i]; m.u[i+1]+=m.u[i]/10; m.u[i]%=10; } if (m.u[l+1]!=0)m.le=l+1; else m.le=l; return m; } bool operator>( const bigint &a){ if (le>a.le) return true ; if (le<a.le) return false ; for ( int i=le;i>=0;i--){ if (u[i]>a.u[i]) return true ; if (u[i]<a.u[i]) return false ; } return false ; } friend ostream& operator<<(ostream &cout,bigint a){ for ( int i=a.le;i>=0;i--) cout<<a.u[i]; return cout; } friend istream& operator>>(istream &cin,bigint &a){ int i,l; char b[82]; cin>>b; memset (a.u,0, sizeof (a.u)); a.le=l= strlen (b)-1; for ( int i=0;i<=l;i++)a.u[l-i]=b[i]- ‘0‘ ; return cin; } bool empty(){ if (le==0&&u[0]==0) return true ; else return false ; } }; bigint a[81],f[81][81]; int n,m; bigint ans; bigint getans( int s, int t){ if (!f[s][t].empty()) return f[s][t]; if (s==t) return f[s][s]=a[s]+a[s]; bigint t1,t2; t1=getans(s+1,t)+a[s]; t2=getans(s,t-1)+a[t]; if (t1>t2) return f[s][t]=t1+t1; else return f[s][t]=t2+t2; } int main(){ cin>>n>>m; for ( int i=1;i<=n;i++){ memset (f,0, sizeof (f)); for ( int j=1;j<=m;j++)cin>>a[j]; ans=ans+getans(1,m); } cout<<ans; return 0; } |
T4:树网的核
对于这道题目首先要做到的是找树的直径,可以得出如果有多条直径的话,随便选取一条就可以了,因为越靠近核一定更优,选取链越长一定越优,(未完待续)
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。