Codeforces Round # 158 (Div.2)
A Adding Digits
题目大意:定义操作(a,b)::在a后面添加一个数字(10进制),并使新的数字能整除b;求a,b执行操作(a,b)n次之后a的值。
思路:第一次操作之后添加0就可以了。
# include <iostream> # include <cstdio> using namespace std; int a,b,n; int main() { scanf("%d%d%d",&a,&b,&n); int t=(b-(a*10%b))%b; if(t<10) { printf("%d%d",a,t); --n;while(n--)printf("0"); } else printf("-1\n"); return 0; }
B Ancient Prophesy
题目大意:给一个字符串,如果一个连续字串满足"dd-mm-yyyy"的日期格式且年份在2013~2015之间,则为合法日期,出现次数最多的合法日期。
思路:可以直接模拟,用map统计;我写了个自动机,感觉用起来很方便,常数上较小。
# include <iostream> # include <cstdio> using namespace std; const int C[11][2]={{1,0},{2,0},{2,3},{4,0},{5,0},{2,6},{7,0},{8,0},{9,6},{10,3},{2,3}}; const int Day[12]={31,28,31,30,31,30,31,31,30,31,30,31}; int HASH[3][12][31],D[1200],Cnt,Ans,w; char a[120000], ans[1200][11]; void pushdata(const char *p) { static int dd,mm,yy; static int *temp; if(*(p+6)!='2' || *(p+7)!='0' || *(p+8)!='1')return; dd=10*(*(p+0)-'0')+(*(p+1)-'0'); mm=10*(*(p+3)-'0')+(*(p+4)-'0'); yy=2010+(*(p+9)-'0'); if(yy<2013 || yy>2015)return; if(mm<1 || mm>12)return; if(dd<1 || dd>Day[mm-1])return; temp=&HASH[yy-2013][mm-1][dd-1]; if(*temp==0)*temp=++Cnt,sprintf(ans[Cnt],"%02d-%02d-%d",dd,mm,yy); D[*temp]++; } int main() { scanf("%s",a); for(int i=0;a[i];i++) { w=C[w][(a[i]=='-')]; if(w==10)pushdata(a+(i-9)); } Ans=1; for(int i=2;i<=Cnt;i++) if(D[i]>D[Ans])Ans=i; printf("%s\n",ans[Ans]); }
C Balls and Boxes
题目大意:有N个盒子,每个里面有一些小球;出题人将一个盒子中的小球全部拿出,然后从下一个开始挨个发球,直到发完为止,第N个的下一个是第1个这样循环;现在已知操作后每个盒子中球的数量和最后一个球发到那个盒子,求操作前盒子里的球数。
思路:通过数学方法推导,可以发现找最少的盒子就可以了,所以直接模拟,注意一些细节。
# include <iostream> # include <cstdio> # define For(i,a,b) for(int i=a;i<=b;i++) # define rep(i,n) For(i,1,n) using namespace std; long long a[100010],m=~0U>>1; int n,x; int getint() { static char c; static int ret; while(!isdigit(c=getchar())); ret=c-'0'; while( isdigit(c=getchar())) ret=ret*10+c-'0'; return ret; } inline void write() { rep(i,n)printf("%lld ",a[i]);printf("\n"); } int main() { n=getint(); x=getint(); rep(i,n) a[i]=getint(); rep(i,n) if(a[i]<m)m=a[i]; if(a[x]==m){rep(i,n)a[i]-=m;a[x]=m*n;write();return 0;} for(int i=x;i;--i)if(a[i]==m){ rep(j,n)a[j]-=m;For(j,i+1,x)a[j]--;a[i]=m*n+x-i;write();return 0; } for(int i=n;i;--i)if(a[i]==m){ rep(j,n)a[j]-=m+1;For(j,x+1,i)a[j]++;a[i]=(m+1)*n-(i-x);write();return 0; } }
D Black and White Tree
题目大意:一棵树黑白染色,知道每个节点染色情况以及每个节点连出边的权值和;求原图(输出所有边和边权)
思路:保证一定有解,限制又很少,所以直接贪心构造即可。
# include <iostream> # include <cstdio> # include <vector> # include <algorithm> using namespace std; #define mp make_pair #define f first #define s second vector<pair<int,int> >v[2]; int main() { int n,i,j,k,t; scanf("%d",&n); for(i=1;i<=n;i++) scanf("%d%d",&t,&k), v[t].push_back(mp(k,i)); sort(v[0].begin(),v[0].end()); sort(v[1].begin(),v[1].end()); for(i=j=0;i<v[0].size()&&j<v[1].size();) { k=min(v[0][i].f,v[1][j].f); printf("%d %d %d\n",v[0][i].s,v[1][j].s,k); v[0][i].f-=k,v[1][j].f-=k; if(v[0][i].f)j++; else if(v[1][j].f)i++; else (i+1<v[0].size())?i++:j++; } return 0; }
E Dividing Kingdom
题目大意:平面上有一堆点,两横两竖四条直线分点集为九部分,给定每部分的点个数,球直线。
大致思路:枚举所有点,O(1)求出直线,然后用线段树判断。O(9!*log n*log n)
# include <iostream> # include <cstdio> # include <vector> # include <algorithm> using namespace std; const int inf=~0U>>1; const int N=100010; #define M tree[u] #define ML tree[u<<1] #define MR tree[u<<1|1] pair<int,int>p[N],q[N]; vector<int>C(9),e; struct Seg{ struct node{ int l,r; vector<int>co; }tree[N<<2]; void init(int u,int l,int r,int L,int R){ M.l=l,M.r=r; int mid=(l+r)>>1,pp; for(int i=L;i<=R;i++){ M.co.push_back(p[i].second); if(p[i].first<=e[mid])pp=i; } sort(M.co.begin(),M.co.end()); if(l==r)return; init(u<<1,l,mid,L,pp); init(u<<1|1,mid+1,r,pp+1,R); } int query(int u,int x,int y){ if(e[M.r]<=x) return upper_bound(M.co.begin(),M.co.end(),y)-M.co.begin(); int ret=query(u<<1,x,y); if(e[MR.l]<=x) ret+=query(u<<1|1,x,y); return ret; } }seg; bool solve() { static int x,xx,y,yy,a,b,c,d; a=C[0]+C[3]+C[6],b=a+C[1]+C[4]+C[7]; x=p[a-1].first,xx=p[b-1].first; if(p[a].first==x||p[b].first==xx)return 0; c=C[0]+C[1]+C[2],d=c+C[3]+C[4]+C[5]; y=q[c-1].first,yy=q[d-1].first; if(q[c].first==y||q[d].first==yy)return 0; if(seg.query(1,x,y)!=C[0])return 0; if(seg.query(1,xx,y)!=C[0]+C[1])return 0; if(seg.query(1,x,yy)!=C[0]+C[3])return 0; if(seg.query(1,xx,yy)!=C[0]+C[1]+C[3]+C[4])return 0; printf("%lf %lf\n%lf %lf\n",x+0.5,xx+0.5,y+0.5,yy+0.5); return true; } int main() { int n,x,y; scanf("%d",&n); for(int i=0;i<n;i++){ scanf("%d%d",&x,&y); p[i]=make_pair(x,y); q[i]=make_pair(y,x); e.push_back(x); } sort(e.begin(),e.end()); e.erase(unique(e.begin(),e.end()),e.end()); sort(p,p+n); sort(q,q+n); seg.init(1,0,e.size()-1,0,n-1); for(int i=0;i<9;i++)scanf("%d",&x),C[i]=x; sort(C.begin(),C.end()); bool flag=false; do{ flag=solve(); if(flag)break; }while(next_permutation(C.begin(),C.end())); if(!flag)printf("-1\n"); return 0; }
P.S :这个stl真方便啊,二分查找,排列组合,去除多余项,排序什么的竟然都有!!用pascal的真心吃亏。。。