hdu 4405 Aeroplane chess
期望dp..倒着推方便一些。 dp[i]记录从i到终点用的次数的期望, dp[0]为答案。
#include <cstring> #include <cstdio> #include <cmath> #include <algorithm> #include <vector> using namespace std; const int maxn=100000+123; double dp[maxn]; int fly[maxn]; const double pr=1.0/6.0; int main() { int n, m; while (~scanf("%d%d", &n, &m), n||m) { memset (fly, -1, sizeof(fly)); for (int i=0; i<m; ++i) { int a, b; scanf("%d%d", &a, &b); fly[a]=b; } memset (dp, 0, sizeof(dp)); for (int i=n-1; i>=0; --i) { if(fly[i]==-1) { for (int j=1; j<=6; ++j) dp[i]+=dp[i+j]*pr; dp[i]+=1.0; } else dp[i]=dp[fly[i]]; ///printf("%d %lf\n", i, dp[i]); } printf("%0.4lf\n", dp[0]); } return 0; } /* 2 0 8 3 2 4 4 5 7 8 */
4407 Sum
容斥, 一开始没注意m=1000. 一直再考虑线段树什么的, 估计是最近做题做蒙圈子了。
后来发现每个操作是可以有O(10^3~10^4)的复杂度, 于是想到对每个op1先求出没改变前的结果, 再将之前所改变的位置计算进去就可以了,op2操作就可以用map直接覆盖原来的数值, 这样保证每个op1时更改的都是最新的操作, 在求某个区间未改变前的sum时, 可以跑个2^7的容斥。
#include <cstring> #include <cstdio> #include <map> #include <iostream> using namespace std; typedef long long ll; bool vis[400010], t[700]; int p[1000],num, num1, ct; int a[400010]; int pp[100]; map<int, int> pos; void init() { num = 0; memset(t, false, sizeof(false)); for (int i = 2; i <= 650; ++i) { if(!t[i]) { p[num++] =i; for(int j = i; j <=650; j += i) t[j] = true; } } return ; } void ppp(int x ) { int i = 0, q = x; while(i < num) { if(q % p[i] == 0) { pp[num1++] = p[i]; while(q % p[i] == 0) q = q / p[i]; } i++; } if(q>1)pp[num1++]=q; return ; } bool check(int x) { for(int i = 0; i < num1; ++i) if(x % pp[i] == 0) return false; return true; } ll sum(ll s, ll t) { return (s+t)*(t-s+1)/2; } int main() { int T; scanf("%d", &T); init(); while (T--) { int x, y, c, o, i, n, m, p; long long ans = 0; pos.clear(); scanf("%d%d", &n, &m); for(i = 1; i <= n; ++i) a[i] = i; for(i = 0; i < m; ++i) { scanf("%d", &o); if(o == 1) { ans = 0; scanf("%d%d%d", &x, &y, &p); num1 = 0; ppp(p); int limit=1<<num1; ///printf("%d %d\n", limit, num1); for (int j=0; j<limit; ++j) { ll pro=1; int cnt=0; for (int sta=j, tt=0; sta; sta>>=1, tt++) { if(sta&1)pro*=pp[tt], cnt++; } if(cnt&1)ans-=sum((x+pro-1)/pro, y/pro)*(ll)pro; else ans+=sum((x+pro-1)/pro, y/pro)*(ll)pro; ///printf("sta=%d %I64d \n", j, ans); } map<int, int>::iterator it; for(it=pos.begin(); it!=pos.end(); ++it) if(it->first>=x && it->first<=y) { if(check(it->second)) ans+=it->second; if(check(it->first)) ans-=it->first; } cout << ans << endl; } else if(o == 2) { int flag = 1; scanf("%d%d", &x, &c); pos[x]=c; } } } return 0; } /* 10 3 3 2 2 3 1 1 3 4 1 2 3 6 15 3 2 13 169 1 2 15 2310 1 2 12 2310 15 5 2 13 13 2 13 169 1 2 15 3 1 2 15 399999 1 1 15 133333 60 3 1 1 60 30 1 2 60 30 1 2 59 30 60 1 1 1 60 1 400000 1 1 1 400000 1 */