C:首先我们可以知道重量为1的方案数就是重量为2的物品的数量,因为只有2 / 2 = 1可以影响它。
那么如果我们从小到大迭代的话,对于当前位置i,只能赋值2 * i才能影响当前位置,那么如果当前方案数的差为d,那么就还需要放d个2 * i。
这里要注意的是差值可能为负数。
#include<bits/stdc++.h> using namespace std; typedef long long LL; typedef pair<int,int> pii; const int N = 1e3 + 5; const int M = 1e7 + 5; const LL Mod = 1e9 + 7; #define rep(at,am,as) for(int at = am;at <= as;++at) #define INF 1e14 #define dbg(ax) cout << "now this num is " << ax << endl; inline long long ADD(long long x,long long y) { if(x + y < 0) return ((x + y) % Mod + Mod) % Mod; return (x + y) % Mod; } inline long long MUL(long long x,long long y) { if(x * y < 0) return ((x * y) % Mod + Mod) % Mod; return x * y % Mod; } inline long long DEC(long long x,long long y) { if(x - y < 0) return (x - y + Mod) % Mod; return (x - y) % Mod; } int m; LL a[N],dp[N]; vector<int> ans; void solve() { cin >> m; rep(i,1,m) cin >> a[i]; rep(i,1,m) { int d = ((a[i] - dp[i]) % Mod + Mod) % Mod; //while(((a[i] - dp[i]) % Mod + Mod) % Mod != 0) { rep(j,1,d) { int w = i * 2; ans.push_back(w); for(int j = m;j >= 1;--j) { if(j - w >= 0) dp[j] = ADD(dp[j],dp[j - w]); if(j - w / 2 >= 0) dp[j] = ADD(dp[j],dp[j - w / 2]); } if(w < N) dp[w] = ADD(dp[w],1); dp[w / 2] = ADD(dp[w / 2],1); } //} } if(ans.size() == 0) ans.push_back(2 * 1000); printf("%d\n",ans.size()); for(auto v : ans) printf("%d ",v); } int main() { // int _; // for(scanf("%d",&_);_;_--) { solve(); //} //system("pause"); return 0; }View Code
H:首先,选定一个点作为轴,那么它就旋转到了父节点处。
那么对于一棵子树,我们要把他的原来的根旋转上来,我们就只需要一直选定原来的根作为轴即可。
旋转的操作就是Splay就行了。
#include<bits/stdc++.h> using namespace std; typedef long long LL; typedef pair<int,int> pii; const int N = 1e3 + 5; const int M = 1e7 + 5; const LL Mod = 998244353; #define rep(at,am,as) for(int at = am;at <= as;++at) #define INF 1e14 #define dbg(ax) cout << "now this num is " << ax << endl; inline long long ADD(long long x,long long y) { if(x + y < 0) return ((x + y) % Mod + Mod) % Mod; return (x + y) % Mod; } inline long long MUL(long long x,long long y) { if(x * y < 0) return ((x * y) % Mod + Mod) % Mod; return x * y % Mod; } inline long long DEC(long long x,long long y) { if(x - y < 0) return (x - y + Mod) % Mod; return (x - y) % Mod; } int n; vector<int> ans; struct Splay { int sons[N][2],f[N],rt; bool vis[N]; inline void Input() { rep(i,1,n) scanf("%d %d",&sons[i][0],&sons[i][1]),f[sons[i][0]] = f[sons[i][1]] = i,vis[sons[i][0]] = vis[sons[i][1]] = 1; rep(i,1,n) if(!vis[i]) rt = i; memset(vis,0,sizeof(vis)); } inline bool chk(int x) {return sons[f[x]][1] == x;} inline void rotate(int x) { ans.push_back(x); int y = f[x], z = f[y], k = chk(x), w = sons[x][k^1]; sons[y][k] = w;f[w] = y; sons[z][chk(y)] = x; f[x] = z; sons[x][k^1] = y; f[y] = x; } inline void splay(int x,int goal = 0) { while(!vis[f[x]] && f[x] != goal) { int y = f[x],z = f[y]; if(!vis[z] && z != goal) { if (chk(x) == chk(y)) rotate(y); else rotate(x); } rotate(x); } } }A,B; void dfs(int rt) { B.splay(rt); B.vis[rt] = 1; if(A.sons[rt][0]) dfs(A.sons[rt][0]); if(A.sons[rt][1]) dfs(A.sons[rt][1]); } void solve() { scanf("%d",&n); A.Input(); B.Input(); dfs(A.rt); printf("%d\n",ans.size()); for(auto v : ans) printf("%d\n",v); } int main() { // int _; // for(scanf("%d",&_);_;_--) { solve(); //} //system("pause"); return 0; }View Code
J:这题挺不错的。
首先我们把[L,R]都转到[0,R]上做处理。
那么就是说对于[0,R]上的点 % P之后在[l,r]里的数量。
那么就分为了k段的[0,P - 1]还有一段多出来的即R % P。
这里我们用线段合并