noip2009 普及组
T1 多项式输出 题目传送门
就是道模拟题咯
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<cstdio> #include<cstring> #include<algorithm> 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,k; int main() { n=read(); k=read(); if(k!=1&&k!=-1) printf("%dx^%d",k,n); else{ if(k==1) printf("x^%d",n); else printf("-x^%d",n); } for(int i=n-1;i;i--){ k=read(); if(!k) continue; if(k>0) printf("+"); if(k==-1) printf("-"); if(k!=1&&k!=-1) printf("%d",k); if(i!=1) printf("x^%d",i); else printf("x"); } k=read(); if(k){ if(k>0) printf("+"); printf("%d\n",k); } return 0; }
T2 分数线划定 题目传送门
也算是道水题 sort一波就好了
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int M=5007; 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,m,cnt,mn; struct node{int w,pos;}e[M]; bool cmp(node a,node b){return a.w!=b.w?a.w>b.w:a.pos<b.pos;} int main() { n=read(); m=read()*3/2; //printf("[%d]\n",m); for(int i=1;i<=n;i++) e[i].pos=read(),e[i].w=read(); sort(e+1,e+1+n,cmp); mn=e[m].w; cnt=m; while(e[cnt+1].w==mn&&cnt<n) cnt++; printf("%d %d\n",mn,cnt); for(int i=1;i<=cnt;i++) printf("%d %d\n",e[i].pos,e[i].w); return 0; }
T3 细胞分裂 题目传送门
这个要用到一个结论
我们将m1分解为一波质数之后可以求出m1由各个质数的几次方(设为h【i】)相乘得到
然后再把h【i】乘上m2
题目就转换成了 吧每个数拆成质数乘积 必须保证组成的质数与m1相同 而每个h【i】的倍数差最大就是这个数的k次方回事m1的m2次方的倍数
再求出所有k取最小值就是答案了
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #define LL long long using namespace std; const int M=15007; 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 m1,m2,cnt,s[M],h[M]; int n,p,sum,v[M],ans=-1; bool f; void prepare(){ int k=1; while(m1!=1){ k++; if(m1%k==0){ cnt++; s[cnt]=k; while(m1%k==0) h[cnt]++,m1=m1/k; h[cnt]=h[cnt]*m2; } } } int main() { n=read(); m1=read(); m2=read(); prepare(); //for(int i=1;i<=cnt;i++) printf("[%d %d %d]\n",s[i],h[i]/m2,m2); for(int i=1;i<=n;i++) v[i]=read(); for(int i=1;i<=n;i++){ f=1; p=0; for(int j=1;j<=cnt;j++){ if(v[i]%s[j]==0){ sum=0; while(v[i]%s[j]==0) sum++,v[i]=v[i]/s[j]; if(h[j]%sum==0) sum=h[j]/sum; else sum=h[j]/sum+1; if(sum>p) p=sum; } else{ f=0; break; } } if(f&&(ans==-1||p<ans)) ans=p; } printf("%d\n",ans); return 0; }
T4 道路游戏 题目传送门
这道题正解是dp 我们很容易想到枚举起点和步数 但是会很容易超时
这时我们发现有一些信息可以累加而不需要多次计算 这样就可以降低复杂度了 233
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int M=1507; 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,m,p; int f[M],s[M][M],w[M],sum; int main() { n=read(); m=read(); p=read(); for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) s[i][j]=read(); for(int i=1;i<=n;i++) w[i]=read(); for(int i=1;i<=m;i++){ for(int j=1;j<=n;j++){ int last=j-1>0?j-1:n; sum=s[last][i]; for(int k=1;k<=p;k++){ if(i-k<0) break; f[i]=max(f[i],f[i-k]-w[last]+sum); last=last-1>0?last-1:n; sum+=s[last][i-k]; } } } printf("%d\n",f[m]); return 0; }