srm 543 div1
2012-05-21 00:25 macaroniz 阅读(229) 评论(0) 收藏 举报250pt
最开始想一位一位的单独求,但是发现计算每一位的0和1很复杂,需要按位dp。
于是想别的方法,注意到如果记SXOR(x)表示0到x的异或和,那么原问题可以转化为SXOR(R)^SXOR(L-1)。
如何快速的求出SXOR(X)呢?
方法有很多,我使用的是按位求。
注意到一个重要的性质:SXOR(2^n-1) = 0,n >= 2。
设X的二进制表示最高位为2^t,因此SXOR(X) =((X - 2^t + 1) % 2 ? 2^t : 0) + SXOR(X - 2^t)
需要对x = 0,1,2,3特判一下就可以了。
class EllysXors { public: long long calc(long long x) { if(x == 3) return 0; if(x == 2) return 3; if(x == 1) return 1; if(x == 0) return 0; long long gao = 0; for(gao = 1;gao*2 <= x;gao = gao*2); long long tmp = 0; if((x - gao + 1) % 2 == 1) tmp = gao; return tmp + calc(x - gao); } long long getXor(long long L, long long R) { if(L == R) return L; return calc(L-1) xor calc(R); } };
500pt
这道题很容易看出状态转移方程,但是朴素的转移代价太大。
切入点在于要看出每个阶段都是凸单调的,并且转移不会出现交叉,即不会出现dp[a] 推出 dp[d],dp[b] 推出 dp[c],a < b,c < d这样的情况。
double dp[51][100100]; class EllysRivers { public:double sqr(int x) { return 1.0*x*x; } double calc_time(int width,int speed,int height) { return sqrt(sqr(width)+sqr(height))/speed; } double getMin(int length, int walk, vector <int> width, vector <int> speed) { double walk_time = 1.0 / walk; int n = speed.size()+1; memset(dp,0,sizeof dp); for(int i = 1;i <= length;i++) dp[0][i] = dp[0][i-1] + walk_time; for(int i = 1;i < n;i++) { int last = 0; for(int j = 0;j <= length;j++) { int lastT = last; dp[i][j] = dp[i-1][last] + calc_time(width[i-1],speed[i-1],j - last); for(int k = last+1;k <= j;k++) { if(dp[i][j] >= dp[i-1][k] + calc_time(width[i-1],speed[i-1],j - k)) { dp[i][j] = dp[i-1][k] + calc_time(width[i-1],speed[i-1],j - k); lastT = k; } else break; } last = lastT; } for(int j = 1;j <= length;j++) dp[i][j] = min(dp[i][j],dp[i][j-1] + walk_time); } //printf("%lf\n",dp[1][4]); return dp[n-1][length]; }
1000pt
浙公网安备 33010602011771号