2016百度之星 初赛2A ABEF
只做了1001 1002 1005 1006。剩下2题可能以后补?
http://acm.hdu.edu.cn/search.php?field=problem&key=2016%22%B0%D9%B6%C8%D6%AE%D0%C7%22+-+%B3%F5%C8%FC%A3%A8Astar+Round2A%A3%A9&source=1&searchmode=source
Solved | Pro.ID | Title | Author | Source | (AC/Submit)Ratio |
5690 | All X | 2016"百度之星" - 初赛(Astar Round2A) | (438/912)48.03% | ||
5691 | Sitting in Line | 2016"百度之星" - 初赛(Astar Round2A) | (255/566)45.05% | ||
5692 | Snacks | 2016"百度之星" - 初赛(Astar Round2A) | (148/689)21.48% | ||
5693 | D Game | 2016"百度之星" - 初赛(Astar Round2A) | (70/212)33.02% | ||
5694 | BD String | 2016"百度之星" - 初赛(Astar Round2A) | (214/477)44.86% | ||
5695 | Gym Class | 2016"百度之星" - 初赛(Astar Round2A) | (266/668)39.82% |
题面看不清楚的可以去下面这个比赛网址看,但是交题要去上面这些交。
http://bestcoder.hdu.edu.cn/contests/contest_show.php?cid=701
都是题面很明显的中文题,我就不写题意了。
1001 All X
题解:
2种解法:1.矩阵快速幂 2.找循环节。我用的是找循环节。
1.快速幂解法:乘十加一这个操作可以转化为乘上一个2*2的矩阵的操作,用快速幂把一大堆矩阵算完,就无敌了。
2.找循环节,观察MOD数不到1W,所以算着算着肯定会出现重复的数,然后就会循环,我们可以跳过若干循环,直接算最后不到1W步的地方。
设y,循环使y=(y*10+1)%MOD,将每个y记录,a[y] = step。a数组初始化-1,当发现a[y]不为-1时,就循环了。
注意有地方要用long long。
代码:
1 //#pragma comment(linker, "/STACK:102400000,102400000") 2 #include<cstdio> 3 #include<cmath> 4 #include<iostream> 5 #include<cstring> 6 #include<algorithm> 7 #include<cmath> 8 #include<map> 9 #include<set> 10 #include<stack> 11 #include<queue> 12 using namespace std; 13 14 #define MZ(array) memset(array, 0, sizeof(array)) 15 #define MF1(array) memset(array, -1, sizeof(array)) 16 #define MINF(array) memset(array, 0x3f, sizeof(array)) 17 #define REP(i,n) for(i=0;i<(n);i++) 18 #define FOR(i,x,n) for(i=(x);i<=(n);i++) 19 #define ROF(i,x,y) for(i=(x);i>=(y);i--) 20 #define RD(x) scanf("%d",&x) 21 #define RD2(x,y) scanf("%d%d",&x,&y) 22 #define RD3(x,y,z) scanf("%d%d%d",&x,&y,&z) 23 #define RD4(x,y,z,w) scanf("%d%d%d%d",&x,&y,&z,&w) 24 #define WN(x) printf("%d\n",x); 25 #define RE freopen("D.in","r",stdin) 26 #define WE freopen("huzhi.txt","w",stdout) 27 #define MP make_pair 28 #define PB push_back 29 #define PF push_front 30 #define PPF pop_front 31 #define PPB pop_back 32 #define lowbit(x) ((x)&(-x)) 33 template<class T>inline void OA(const T &a,const int &st,const int &ed) { 34 if(ed>=st)cout<<a[st]; 35 int i; 36 FOR(i,st+1,ed)cout<<' '<<a[i]; 37 puts(""); 38 } 39 typedef long long LL; 40 typedef unsigned long long ULL; 41 const double PI=acos(-1.0); 42 const double EPS=1e-10; 43 inline int sgn(double &x) { 44 if(fabs(x) < EPS)return 0; 45 if(x < 0)return -1; 46 else return 1; 47 } 48 49 const int MAXN=111111; 50 const int MAXM=33; 51 52 LL x,k,c; 53 LL m; 54 55 LL h[11111]; 56 57 bool farm() { 58 LL y = 0; 59 LL l = 0; 60 MF1(h); 61 h[0] = 0; 62 while(l<m) { 63 y = y*10+x; 64 y %= k; 65 l++; 66 if(h[y]!=-1) { 67 break; 68 } 69 h[y] = l; 70 } 71 if(l<m) { 72 LL st = h[y]; 73 LL ed = l; 74 LL step = ed - st; 75 LL jump = (m-l)/step; 76 l += jump*step; 77 while(l<m) { 78 y = y*10+x; 79 y %= k; 80 l++; 81 } 82 } 83 84 return y==c; 85 } 86 87 int main() { 88 int i; 89 int T,t=1; 90 RD(T); 91 while(T--) { 92 cin>>x>>m>>k>>c; 93 printf("Case #%d:\n",t++); 94 if(farm())puts("Yes"); 95 else puts("No"); 96 } 97 return 0; 98 }
1002 Sitting in Line
题解:
状压动规。
注意只有16个数,用了哪些数的状态可以用16位二进制表示。然后想局部最优性,我们可以先算前x个位置放各种数的情况,再推到x+1位置,所需要的信息是第x个是哪个数。
可以设定状态dp[x][y],x为那个16位二进制,y为已放好的数中最右边那个是什么。
就一顿状态转移。如果已经有数占据一个位置了,就只转移到以这个数结尾的状态。
(可恶,这题我比赛时没想出来,动规苦手)
代码:
1 #pragma comment(linker, "/STACK:102400000,102400000") 2 #include<cstdio> 3 #include<cmath> 4 #include<iostream> 5 #include<cstring> 6 #include<algorithm> 7 #include<cmath> 8 #include<map> 9 #include<set> 10 #include<stack> 11 #include<queue> 12 using namespace std; 13 14 #define MZ(array) memset(array, 0, sizeof(array)) 15 #define MF1(array) memset(array, -1, sizeof(array)) 16 #define MINF(array) memset(array, 0x3f, sizeof(array)) 17 #define REP(i,n) for(i=0;i<(n);i++) 18 #define FOR(i,x,n) for(i=(x);i<=(n);i++) 19 #define ROF(i,x,y) for(i=(x);i>=(y);i--) 20 #define RD(x) scanf("%d",&x) 21 #define RD2(x,y) scanf("%d%d",&x,&y) 22 #define RD3(x,y,z) scanf("%d%d%d",&x,&y,&z) 23 #define RD4(x,y,z,w) scanf("%d%d%d%d",&x,&y,&z,&w) 24 #define WN(x) printf("%d\n",x); 25 #define RE freopen("D.in","r",stdin) 26 #define WE freopen("huzhi.txt","w",stdout) 27 #define MP make_pair 28 #define PB push_back 29 #define PF push_front 30 #define PPF pop_front 31 #define PPB pop_back 32 #define lowbit(x) ((x)&(-x)) 33 template<class T>inline void OA(const T &a,const int &st,const int &ed) { 34 if(ed>=st)cout<<a[st]; 35 int i; 36 FOR(i,st+1,ed)cout<<' '<<a[i]; 37 puts(""); 38 } 39 typedef long long LL; 40 typedef unsigned long long ULL; 41 const double PI=acos(-1.0); 42 const double EPS=1e-10; 43 inline int sgn(double &x) { 44 if(fabs(x) < EPS)return 0; 45 if(x < 0)return -1; 46 else return 1; 47 } 48 49 const int INF = 0x3f3f3f3f; 50 const int MAXN=111111; 51 const int MAXM=16; 52 const int MM = 1111111; 53 54 int n; 55 int a[MAXM],p[MAXM]; 56 57 int b[1<<MAXM][MAXM]; 58 int c[MAXM]; 59 60 int q[2][MM]; 61 int w[2][MM]; 62 int qn[2]; 63 inline int farm() { 64 int i,j,k,y; 65 int now=0; 66 int maxx = 1<<n; 67 REP(i,maxx)REP(j,n)b[i][j]=-1; 68 MF1(c); 69 REP(i,n) { 70 if(p[i]!=-1)c[p[i]]=i; 71 } 72 ///DP INIT 73 int st,ed; 74 if(c[0]==-1) { 75 st=0; 76 ed=n-1; 77 } else st=ed=c[0]; 78 79 FOR(i,st,ed) { 80 y = 1<<i; 81 b[y][i] = 0; 82 q[now][qn[now]] = y; 83 w[now][qn[now]] = i; 84 qn[now]++; 85 } 86 now^=1; 87 int ans=0x80000001; 88 ///DP zhuan yi 89 FOR(i,1,n-1) { 90 int &nn = qn[now]; 91 int &pn = qn[now^1]; 92 int st,ed; 93 if(c[i]!=-1) { 94 st=ed=c[i]; 95 } else { 96 st=0; 97 ed=n-1; 98 } 99 nn=0; 100 FOR(j,st,ed) { 101 y = 1<<j; 102 REP(k,pn) { 103 int &qq =q[now^1][k]; 104 int &ww = w[now^1][k]; 105 if((qq & y)!=0)continue; 106 // printf("%d, %d:%d, %d:%d\n",i,j,a[j], k,ww); 107 int z = qq | y; 108 int newY = b[qq][ww] + a[ww] * a[j]; 109 if(b[z][j]==-1 || newY > b[z][j]) { 110 b[z][j]=newY; 111 // printf("%d,%d,%d\n",z,j,newY); 112 if(i==n-1) ans = max(ans, newY); 113 q[now][nn] = z; 114 w[now][nn] = j; 115 nn++; 116 } 117 } 118 } 119 now^=1; 120 } 121 return ans; 122 } 123 124 int main() { 125 int i,x,y; 126 int L,R; 127 int T,t=1; 128 RD(T); 129 while(T--) { 130 RD(n); 131 REP(i,n)RD2(a[i],p[i]); 132 printf("Case #%d:\n",t++); 133 printf("%d\n",farm()); 134 } 135 return 0; 136 }
1005 BD String
题解:
疯狂递归。
观察题目,可以发现这个第i个字符串的前半部分其实就是第i-1个字符串。它搞第2^1000个字符串,简直吓人,其实我们只用前面一小部分就行了。
用gank(L,R)递归求区间[L,R]的B数。
观察发现,那个中间的B总是在2的某次方上,我们要以这些B作为分界线。现在先称这些B为“中B”。
要求区间[L,R],我们找R左边的最右边的一个中B,这个中B,很关键。可以用log2得到。
如果L大于这个中B,我们可以根据规则递归,把区间以中B为轴,镜像到中B的左边。
如果区间包括中B,记得返回值要加1。
如果L小于这个中B,则[中B +1,R]这个区间根据上面的说法,是要镜像到左边的,这样就会和[L, 中B-1]重合,最后发现重合的这一段就抵消掉了(因为镜像到左边是要求D的数量,也就是总数减去B数,减去哦),所以我们只用算不重合的。
这样这个区间就会以log的速度减小,一下就算完了。
(比赛时没做出,没能认真下来思考题,被2^1000吓到了)
代码:
1 //#pragma comment(linker, "/STACK:102400000,102400000") 2 #include<cstdio> 3 #include<cmath> 4 #include<iostream> 5 #include<cstring> 6 #include<algorithm> 7 #include<cmath> 8 #include<map> 9 #include<set> 10 #include<stack> 11 #include<queue> 12 using namespace std; 13 14 #define MZ(array) memset(array, 0, sizeof(array)) 15 #define MF1(array) memset(array, -1, sizeof(array)) 16 #define MINF(array) memset(array, 0x3f, sizeof(array)) 17 #define REP(i,n) for(i=0;i<(n);i++) 18 #define FOR(i,x,n) for(i=(x);i<=(n);i++) 19 #define ROF(i,x,y) for(i=(x);i>=(y);i--) 20 #define RD(x) scanf("%d",&x) 21 #define RD2(x,y) scanf("%d%d",&x,&y) 22 #define RD3(x,y,z) scanf("%d%d%d",&x,&y,&z) 23 #define RD4(x,y,z,w) scanf("%d%d%d%d",&x,&y,&z,&w) 24 #define WN(x) printf("%d\n",x); 25 #define RE freopen("D.in","r",stdin) 26 #define WE freopen("huzhi.txt","w",stdout) 27 #define MP make_pair 28 #define PB push_back 29 #define PF push_front 30 #define PPF pop_front 31 #define PPB pop_back 32 #define lowbit(x) ((x)&(-x)) 33 template<class T>inline void OA(const T &a,const int &st,const int &ed) { 34 if(ed>=st)cout<<a[st]; 35 int i; 36 FOR(i,st+1,ed)cout<<' '<<a[i]; 37 puts(""); 38 } 39 typedef long long LL; 40 typedef unsigned long long ULL; 41 const double PI=acos(-1.0); 42 const double EPS=1e-10; 43 inline int sgn(double &x) { 44 if(fabs(x) < EPS)return 0; 45 if(x < 0)return -1; 46 else return 1; 47 } 48 49 const int MAXN=111111; 50 const int MAXM=33; 51 52 int a[1]; 53 54 inline LL farm(const LL &l, const LL &r) { 55 if(l>r)return 0; 56 double lgr = log(r)/log(2); 57 int ilgr = floor(lgr ); 58 LL edge = (1LL<<ilgr); 59 // printf("[%I64d,%I64d],%I64d\n",l,r,edge); 60 if(l>edge){ 61 return (r-l+1) - farm(edge - (r-edge),edge - (l-edge)); 62 }else if(l<edge && r>edge){ 63 LL re = 1; 64 if(r-edge > edge-l){ 65 ///re += farm(l,edge-1) + (edge-l+1-1) - farm(l,edge-1); 66 re += edge-l; 67 re += farm(edge+(edge-l)+1, r); 68 }else{ 69 ///re += (r-edge+1-1) - farm(edge - (r-edge) , edge - 1) + farm(...); 70 re += r-edge; 71 re += farm(l, edge - (r-edge) - 1); 72 } 73 return re; 74 }else if(l==edge){ 75 if(r==edge) return 1; 76 else return (r-edge) - farm(edge - (r-edge),edge - 1) + 1; 77 }else if(r==edge){ 78 return farm(l,r-1) + 1; 79 }else{ 80 for(int i=0;true;i--) 81 a[i]++; 82 } 83 } 84 85 int main() { 86 LL L,R; 87 int T; 88 RD(T); 89 while(T--) { 90 scanf("%I64d%I64d",&L,&R); 91 printf("%I64d\n",farm(L,R)); 92 } 93 return 0; 94 }
1006 Gym Class
题解:
贪心。
分析题,首先想把越大的放越前面,但是有人恨他的话,恨他的人要放在更前面。
再一想,也就是有人恨的人,先不能放,先要放没人恨的人。
再一想,放了没人恨的人,它就不会影响到它恨的人,可以把它恨的人的【被恨次数】减一,它恨的人可能就变成没人恨的人。变成了没人恨的人,就有了加入排队的机会。
所以我们就用一个优先队列这样搞就行了。
(我用的是set,比赛时没想清楚就写了,把有人恨的也丢进set了,后来超时,改了一下才过,写题前的思考与规划需要改进)
代码:
1 //#pragma comment(linker, "/STACK:102400000,102400000") 2 #include<cstdio> 3 #include<cmath> 4 #include<iostream> 5 #include<cstring> 6 #include<algorithm> 7 #include<cmath> 8 #include<map> 9 #include<set> 10 #include<stack> 11 #include<queue> 12 using namespace std; 13 14 #define MZ(array) memset(array, 0, sizeof(array)) 15 #define MF1(array) memset(array, -1, sizeof(array)) 16 #define MINF(array) memset(array, 0x3f, sizeof(array)) 17 #define REP(i,n) for(i=0;i<(n);i++) 18 #define FOR(i,x,n) for(i=(x);i<=(n);i++) 19 #define ROF(i,x,y) for(i=(x);i>=(y);i--) 20 #define RD(x) scanf("%d",&x) 21 #define RD2(x,y) scanf("%d%d",&x,&y) 22 #define RD3(x,y,z) scanf("%d%d%d",&x,&y,&z) 23 #define RD4(x,y,z,w) scanf("%d%d%d%d",&x,&y,&z,&w) 24 #define WN(x) printf("%d\n",x); 25 #define RE freopen("D.in","r",stdin) 26 #define WE freopen("huzhi.txt","w",stdout) 27 #define MP make_pair 28 #define PB push_back 29 #define PF push_front 30 #define PPF pop_front 31 #define PPB pop_back 32 #define lowbit(x) ((x)&(-x)) 33 template<class T>inline void OA(const T &a,const int &st,const int &ed) { 34 if(ed>=st)cout<<a[st]; 35 int i; 36 FOR(i,st+1,ed)cout<<' '<<a[i]; 37 puts(""); 38 } 39 typedef long long LL; 40 typedef unsigned long long ULL; 41 const double PI=acos(-1.0); 42 const double EPS=1e-10; 43 inline int sgn(double &x) { 44 if(fabs(x) < EPS)return 0; 45 if(x < 0)return -1; 46 else return 1; 47 } 48 49 const int MAXN=111111; 50 const int MAXM=33; 51 52 struct Edge { 53 int y; 54 int next; 55 } e[MAXN]; 56 int en; 57 int head[MAXN]; 58 59 inline void addEdge(const int &x,const int &y) { 60 e[en].y = y; 61 e[en].next = head[x]; 62 head[x] = en; 63 en++; 64 } 65 66 int n,m; 67 pair<int,int> a[MAXN]; 68 69 set<int>st; 70 set<int>::iterator it; 71 72 inline void del1enemy(const int &x) { 73 a[x].first--; 74 if(a[x].first==0)st.insert(a[x].second); 75 } 76 77 inline LL farm() { 78 int i,j; 79 st.clear(); 80 FOR(i,1,n) { 81 if(a[i].first==0) st.insert(a[i].second); 82 } 83 LL re = 0; 84 int mi = 12345678; 85 FOR(i,1,n) { 86 it = st.begin(); 87 int x= (*it); 88 mi = min(mi, -x); 89 re+=mi; 90 st.erase(it); 91 j = head[-x]; 92 while(j!=-1) { 93 del1enemy(e[j].y); 94 j = e[j].next; 95 } 96 } 97 return re; 98 } 99 100 int main() { 101 int i,x,y; 102 int T; 103 RD(T); 104 FOR(i,1,100000){ 105 a[i].second = -i; 106 } 107 while(T--) { 108 RD2(n,m); 109 en=0; 110 MF1(head); 111 FOR(i,1,n) { 112 a[i].first=0; 113 } 114 REP(i,m) { 115 RD2(x,y); 116 addEdge(x,y); 117 a[y].first++; 118 } 119 cout<<farm()<<endl; 120 } 121 return 0; 122 }