标签:style blog http io ar os sp for on
写个暴力程序会发现若n*r*c 是偶数,则是必败态,输出0.000000
否则对于3*3*3 赢的位置有:
1 0 1
0 1 0
1 0 1
0 1 0
1 0 1
0 1 0
1 0 1
0 1 0
1 0 1
1为必胜点。也就是说左上角是1,这样扩散出去。
答案就是所有1位置的概率和。
题解:点击打开链接
因为k很小
公式: ((dep[y]-dep[x])%k+1)*val
当确定depx后每隔k个深度增加的点权就是一个定值。
思路:
先dfs得到dfs序,然后建k个线段树,把(dep[i] - dep[1] )%k相同的放到一个线段树内操作。
当然我们不需要把点分开处理,因为只要查询时定位好点所在的线段树就可以了。
#include <cstdio> #include <cstring> #include <vector> #include <cmath> #include <iostream> #include <algorithm> using namespace std; #define lson l, mid, rt<<1 #define rson mid+1,r, rt<<1|1 typedef long long ll; const int N =50000+10; const int M = N+N; // template <class T> inline bool rd(T &ret) { char c; int sgn; if(c=getchar(),c==EOF) return 0; while(c!='-'&&(c<'0'||c>'9')) c=getchar(); sgn=(c=='-')?-1:1; ret=(c=='-')?0:(c-'0'); while(c=getchar(),c>='0'&&c<='9') ret=ret*10+(c-'0'); ret*=sgn; return 1; } template <class T> inline void pt(T x) { if (x <0) { putchar('-'); x = -x; } if(x>9) pt(x/10); putchar(x%10+'0'); } // struct Edge { int v, nex; Edge() { } Edge(int _v, int _nex) { v = _v; nex = _nex; } }; struct node { ll v, addv; }; struct Seg { node a[N<<2]; void build(int l, int r, int rt) { a[rt].v = a[rt].addv = 0; if (l != r) { int mid = (l+r)>>1; build(lson); build(rson); } } void Down(node& fa, node& ls, node& rs) { if (fa.addv!=0) { ls.addv += fa.addv; ls.v += fa.addv; rs.addv += fa.addv; rs.v += fa.addv; fa.addv = 0; } } void update(int L, int R, ll v, int l, int r, int rt) { if (L<=l && r<=R) { a[rt].addv += v; a[rt].v += v; } else { Down(a[rt], a[rt<<1], a[rt<<1|1]); int mid = (l+r)>>1; if (R<=mid) update(L, R, v,lson); else if (L>mid) update(L, R, v,rson); else { update(L, mid, v, lson); update(mid+1, R, v, rson); } } } void query(int pos, int l, int r, int rt) { if (l == r) { //putchar('-'); pt(a[rt].v); putchar('\n'); } else { Down(a[rt], a[rt<<1], a[rt<<1|1]); int mid = (l+r)>>1; if (pos<=mid) query(pos, lson); else query(pos, rson); } } }sol[5]; int T = 0, n, K, d[N]; int dep, pos[N], son[N]; int g[N], idx; Edge e[M]; void add(int u, int v) { e[idx] = Edge(v, g[u]); g[u] = idx++; } void dfs(int v, int u, int fa) { ++ dep; pos[u] = dep; son[u] = 1; d[u] = v%K; for (int i = g[u]; ~i; i = e[i].nex) if (e[i].v!=fa) { dfs(v+1, e[i].v, u); son[u] += son[e[i].v]; } } int sub(int x, int y) { return ((y-x)%K+K)%K; } void work() { int m, typ, x, u, v; rd(n); rd(m); rd(K); idx = 0; memset(g, -1, sizeof(int)*(n+2)); for (int i = 0; i < n-1; ++i) { rd(u); rd(v); add(u, v); add(v, u); } dep = 0; dfs(0, 1, -1); for (int i = 0; i < K; ++i) sol[i].build(1, n, 1); printf("Case#%d:\n", ++T); while (m-->0) { scanf("%d", &typ); if (typ == 1) { rd(u); rd(v); x = d[u]; for (int j = 0; j < K; ++j) sol[j].update(pos[u], pos[u]+son[u]-1, (ll)(sub(x,j)+1)*v, 1, n, 1); } else { rd(u); sol[d[u]].query(pos[u], 1, n, 1); } } } int main() { int cas; scanf("%d", &cas); while (cas-->0) { work(); } return 0; }
思路:
n^2的dp dp[i]表示前i个数的最大价值
dp[i] = max(dp[j] + (a[i]-a[j])*(a[i]-a[j]));
思路:
我们先把礼物平均分成2堆。
然后枚举1-(n/2)的所有二进制状态。0就给a,1就给b。
我们设此时a获得的价值和为A,b获得的价值和为B
那么对于一个状态我们就能得到 B-A。
给所有B-A排个序,得到数组K
对于另一半(n/2+1) - n也这样枚举得到A-B.然后去K数组中二分查找距离-(A-B)最近的数即可。
记忆化搜索,从个位开始构造
Lcm(1-9) = 2520
Codeforces 55D : 点击打开链接
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; typedef long long ll; const int N = 105; const int M = 3005;//LCM(1..9) = 2520; int a[N], num[M], cnt; ll dp[N][N][M];//dp[i][j][k]表示考虑后i位的lcm是j,和为k的数的个数 int gcd(int a, int b) { while(a>0 && b>0) { if(a > b) a = a%b; else b = b%a; } return a+b; } void pre() { cnt = 0; for(int i = 1; i <= 2520; i ++) { if(2520 % i == 0) { num[i] = cnt++; } } memset(dp, -1, sizeof dp); } ll dfs(int len, int lcm, int sum, bool f) { if(len == 0) { if(sum%lcm == 0) return 1; else return 0; } if(!f && dp[len][num[lcm]][sum] != -1) { return dp[len][num[lcm]][sum]; } ll ans = 0; int Max = f?a[len]:9; for(int i = 0; i <= Max; i ++) { int nlcm; if(i == 0) nlcm = lcm; else nlcm = lcm/__gcd(lcm, i)*i; ans += dfs(len-1, nlcm, (sum *10 + i) % 2520, f && i == Max); } if(!f) dp[len][num[lcm]][sum] = ans; return ans; } ll cal(ll n) { int size = 0; while(n > 0) { a[++size] = n%10; n /= 10; } ll ans = dfs(size, 1, 0, true); return ans; } int main() { pre(); int T; scanf("%d", &T); while(T--) { ll b; cin>>b; cout<<cal(b) - 1<<endl; } }
搜索+剪枝
题解:点击打开链接
圆桌骑士。poj 2942.白书上的原题。。最后答案改成 n-ans即可
标签:style blog http io ar os sp for on
原文地址:http://blog.csdn.net/qq574857122/article/details/41173519