百度之星Astar2016 Round2A

All X

等比数列求和一下 A/B MOD C = A MOD (B*C) / B  或者分治一下

Sitting in Line

状压+拓扑dp

dp(i, j)表示当前二进制状态为j,当前状态的最后一个数字是a[i],然后按照拓扑序dp进行更新,并用一个bool数组记录是否在队列中。

网上还有其他优美的姿势,按某种枚举方式可以达到拓扑序。

 1 #include <bits/stdc++.h>
 2 typedef long long ll;
 3 using namespace std;
 4 int a[20], p[20], n; //输入的第i个数是否固定
 5 int vis[20], now[20];//输出的第i个数是否确定
 6 ll dp[16][1<<16];
 7 bool isin[16][1<<16];
 8 struct P{
 9     int x, y;
10     P(){}
11     P(int x, int y):x(x), y(y){}
12 };
13 
14 int main(){
15     int T, ca = 1;
16     cin>>T;
17     while(T--){
18         memset(vis, 0, sizeof(vis));
19         cin>>n;
20         for(int i = 0; i < n; i++){
21             cin>>a[i]>>p[i];
22             if(p[i] != -1){
23                 vis[ p[i] ] = true;
24                 now[ p[i] ] = i;
25             }
26         }
27 
28         memset(dp, 0x80, sizeof(dp));
29         memset(isin, 0, sizeof(isin));
30         queue<P> Q;
31         if(vis[0]){
32             dp[ now[0] ][ 1<<now[0] ] = 0;
33             isin[ now[0] ][ 1<<now[0] ] = true;
34             Q.push( P(now[0], 1<<now[0]) );
35         }
36         else{
37             for(int i = 0; i < n; i++)
38                 if(p[i] == -1){
39                     dp[i][1<<i] = 0;
40                     isin[i][1<<i] = true;
41                     Q.push( P(i, 1<<i) );
42                 }
43         }
44 
45         for(int i = 1; i < n; i++){//pos
46             int size = Q.size();
47             for(int j = 0; j < size; j++){
48                 P pp = Q.front();
49                 Q.pop();
50                 if(vis[i]){
51                     dp[ now[i] ][ pp.y|(1<<now[i]) ] = max(dp[ now[i] ][ pp.y|(1<<now[i]) ] , dp[pp.x][pp.y]+a[pp.x]*a[ now[i] ]);
52                     if(isin[ now[i] ][ pp.y|(1<<now[i]) ] == false)
53                         Q.push( P(now[i], pp.y|(1<<now[i])) ), isin[ now[i] ][ pp.y|(1<<now[i]) ] = true;
54                 }
55                 else{
56                     for(int k = 0; k < n; k++){
57                         if( (pp.y&(1<<k)) == 0&&p[k] == -1){
58                             dp[k][pp.y|(1<<k)] = max(dp[k][pp.y|(1<<k)] , dp[pp.x][pp.y]+a[pp.x]*a[k]);
59                             if(isin[ k ][ pp.y|(1<<k) ] == false)
60                                 Q.push( P(k, pp.y|(1<<k)) ), isin[ k ][ pp.y|(1<<k) ] = true;
61                         }
62                     }
63                 }
64             }
65         }
66 
67         ll ans = -1e17;
68         for(int i = 0; i < n; i++)
69             ans = max(ans, dp[i][ (1<<n)-1 ]);
70         printf("Case #%d:\n", ca++);
71         cout<<ans<<endl;
72     }
73     return 0;
74 }
View Code

BD String

从某个点断开后,后面的部分折到前面来,刚好和前面部分的后半段拼成一个整体。

 1 #include <bits/stdc++.h>
 2 typedef long long ll;
 3 using namespace std;
 4 
 5 ll getsum(ll x){
 6     if(x <= 2)
 7         return x;
 8 
 9     ll fir = 1;
10     while( fir*2 <= x)
11         fir <<= 1;
12 
13     return 1LL+x-fir + getsum( fir-(x-fir)-1 );
14 }
15 int main(){
16     int t, ca = 1;
17     ll l, r;
18     cin>>t;
19     while(t--){
20         cin>>l>>r;
21         ll ans = getsum(r)-getsum(l-1);
22         cout<<ans<<endl;
23     }
24     return 0;
25 }
View Code

Gym Class

SB拓扑排序即可。

posted @ 2016-05-23 17:26  我在地狱  阅读(192)  评论(0编辑  收藏  举报