A:因为数太大,所以按字符串存即可
#include<bits/stdc++.h> using namespace std; typedef long long LL; typedef long double ld; typedef pair<LL,int> pii; const int N = 1e5+5; const int M = 2e6+5; const LL Mod = 998244353; #define rg register #define pi acos(-1) #define INF 1e18 #define INM INT_MIN #define dbg(ax) cout << "now this num is " << ax << endl; inline int read() { int x = 0,f = 1;char c = getchar(); while(c < '0' || c > '9'){if(c == '-') f = -1;c = getchar();} while(c >= '0' && c <= '9'){x = (x<<1)+(x<<3)+(c^48);c = getchar();} return x*f; } int main() { ios::sync_with_stdio(false); cin.tie(0);cout.tie(0); string s; while(getline(cin,s)) { string t = ""; vector<string> ans; int pre = 0; for(int i = 0;i < s.size();++i) { if(s[i] >= '0' && s[i] <= '9') { if(s[i] == '0' && t == "") pre++; else t += s[i]; } else { if(t != "") ans.push_back(t); else if(t == "" && pre != 0) ans.push_back("0"); pre = 0; t = ""; } } if(t != "") ans.push_back(t); else if(t == "" && pre != 0) ans.push_back("0"); if(ans.size() == 0) cout << endl; else { for(int i = 0;i < ans.size();++i) { cout << ans[i]; if(i == ans.size()-1) cout << endl; else cout << " "; } } } // system("pause"); return 0; }
B:显然是最大的那个数
#include<bits/stdc++.h> using namespace std; typedef long long LL; typedef long double ld; typedef pair<LL,int> pii; const int N = 1e5+5; const int M = 2e6+5; const LL Mod = 998244353; #define rg register #define pi acos(-1) #define INF 1e18 #define INM INT_MIN #define dbg(ax) cout << "now this num is " << ax << endl; inline int read() { int x = 0,f = 1;char c = getchar(); while(c < '0' || c > '9'){if(c == '-') f = -1;c = getchar();} while(c >= '0' && c <= '9'){x = (x<<1)+(x<<3)+(c^48);c = getchar();} return x*f; } int main() { int ca;ca = read(); while(ca--) { int n;n = read(); int mx = -1; for(int i = 1;i <= n;++i) { int x;x = read(); mx = max(mx,x); } if(mx < 0) mx = 0; printf("%d\n",mx); } // system("pause"); return 0; }
C:手推几个就可以发现3的倍数必败,其他必胜
#include<bits/stdc++.h> using namespace std; typedef long long LL; typedef long double ld; typedef pair<LL,int> pii; const int N = 1e5+5; const int M = 2e6+5; const LL Mod = 998244353; #define rg register #define pi acos(-1) #define INF 1e18 #define INM INT_MIN #define dbg(ax) cout << "now this num is " << ax << endl; inline LL read() { LL x = 0,f = 1;char c = getchar(); while(c < '0' || c > '9'){if(c == '-') f = -1;c = getchar();} while(c >= '0' && c <= '9'){x = (x<<1)+(x<<3)+(c^48);c = getchar();} return x*f; } int main() { int ca;ca = read(); while(ca--) { LL n;n = read(); if(n%3 == 0) printf("Frame\n"); else printf("Alan\n"); } // system("pause"); return 0; }
D:DP转移
#include<bits/stdc++.h> using namespace std; typedef long long LL; typedef long double ld; typedef pair<LL,int> pii; const int N = 1e5+5; const int M = 2e6+5; const LL Mod = 998244353; #define rg register #define pi acos(-1) #define INF 1e18 #define INM INT_MIN #define dbg(ax) cout << "now this num is " << ax << endl; inline LL read() { LL x = 0,f = 1;char c = getchar(); while(c < '0' || c > '9'){if(c == '-') f = -1;c = getchar();} while(c >= '0' && c <= '9'){x = (x<<1)+(x<<3)+(c^48);c = getchar();} return x*f; } int a[N]; int dp[N][2],f[N];//dp[i][0]-全变0的最小代价,dp[i][1]-全变1的最小代价 int main() { int n;n = read(); for(int i = 1;i <= n;++i) a[i] = read(); int sum = 0; if(a[1] == 1) { dp[1][1] = 0; dp[1][0] = 1; } else { dp[1][0] = 0; dp[1][1] = 1; } for(int i = 2;i <= n;++i) { if(a[i] == 0) { dp[i][0] = min(dp[i-1][0],dp[i-1][1]+1); dp[i][1] = min(dp[i-1][1]+1,dp[i-1][0]+1); } else { dp[i][1] = min(dp[i-1][1],dp[i-1][0]+1); dp[i][0] = min(dp[i-1][1]+1,dp[i-1][0]+1); } // printf("i is %d dp0 is %d dp1 is %d\n",i,dp[i][0],dp[i][1]); } int ans = min(dp[n][0],dp[n][1]+1); printf("%d\n",ans); //system("pause"); return 0; }
E:
注意lowbit的定义是最小的为1的二进制位。
首先暴力建边n*2,可以不行。
这里建32个虚拟点,表示二进制位i的站点。
那么可以发现,如果这个数i位上是1,那么就可以和代表i的虚拟点连边,代价为(1<<i)。
然后虚拟点到其他点的代价都为0.最后跑一次最短路即可。
那么,为什么这样建边就能保证最小了,不会比原先的答案还小吗?
可以发现,如果可以建边,那么说明这个数这个位上有1,如果更低位上有1,那么会满足lowbit的定义。
显然,会用更低的代价去松弛答案,这样可以保证到最小。至于不会超答案,这很显然,如果能到,说明可以松弛到。
#include<bits/stdc++.h> using namespace std; typedef long long LL; typedef long double ld; typedef pair<LL,int> pii; const int N = 1e5+5; const int M = 2e6+5; const LL Mod = 998244353; #define rg register #define pi acos(-1) #define INF 1e18 #define INM INT_MIN #define dbg(ax) cout << "now this num is " << ax << endl; inline LL read() { LL x = 0,f = 1;char c = getchar(); while(c < '0' || c > '9'){if(c == '-') f = -1;c = getchar();} while(c >= '0' && c <= '9'){x = (x<<1)+(x<<3)+(c^48);c = getchar();} return x*f; } LL a[N],dis[N<<1]; struct Node{int to;LL dis;}; vector<Node> G[N<<1]; /* [0,34] - [] */ int n,m; void slove() { for(int i = 1;i <= m;++i) dis[i] = INF; priority_queue<pii,vector<pii>,greater<pii> > Q; dis[1] = 0; Q.push(pii{0,1}); while(!Q.empty()) { int u = Q.top().second; LL d = Q.top().first; Q.pop(); if(d > dis[u]) continue; for(auto t : G[u]) { if(dis[t.to] > dis[u]+t.dis) { dis[t.to] = dis[u]+t.dis; Q.push(pii{dis[t.to],t.to}); } } } } int main() { int ca;ca = read(); while(ca--) { n = read(); for(rg int i = 1;i <= n;++i) a[i] = read(); m = n+35; for(rg int i = 1;i <= m;++i) G[i].clear(); for(rg int i = 1;i <= n;++i) { for(rg int j = 0;j < 35;++j) { if((a[i]>>j)&1) { G[i].push_back(Node{n+j+1,1LL<<j}); G[n+j+1].push_back(Node{i,0}); } } } slove(); if(dis[n] == INF) printf("Impossible\n"); else printf("%lld\n",dis[n]); } //system("pause"); return 0; }
F:
一开始一直在想树剖来着。。(不过树剖也可以做)。
解法:可以发现,对于区间[L,R]里的最大权值,显然是区间的直径(即区间内最远的两个点)
那么我们可以用st[i][j]来表示i位置包含i后面开始2^j个位置里的直接的两个数,因为是两个数,可以要用pair来存。
那么st[i][j]合并,这里可以发现,是类似st表的合并。从st[i][j-1]和st[i+(1<<j)][j-1]来转移。
这里我们还可以发现的是,对于两个区间的直径的合并,显然新的直径是四个点里(即原先两个区间的直径点)距离最远的两个点。(这也很显然,可以画图理解,就三种链与点的关系)
那么我们就可以转移最大值。到这里就差不多了。
但是这题卡时间卡的厉害。vector被卡。然后因为LCA也用了太多次了,必须用ST来求LCA,不然也会T
#include<bits/stdc++.h> using namespace std; typedef long long LL; typedef long double ld; typedef pair<int,int> pii; const int N = 3e5+5; const int M = 2e6+5; const LL Mod = 998244353; #define rg register #define pi acos(-1) #define INF 1e18 #define INM INT_MIN #define dbg(ax) cout << "now this num is " << ax << endl; inline int read() { int x = 0,f = 1;char c = getchar(); while(c < '0' || c > '9'){if(c == '-') f = -1;c = getchar();} while(c >= '0' && c <= '9'){x = (x<<1)+(x<<3)+(c^48);c = getchar();} return x*f; } int lg[N<<1],head[N],f[N<<1][20],dfn[N],dep[N]; LL way[N]; int n,q,cnt = 0,tot = 0; pii st[N][32]; struct Node{int to,next;LL dis;}e[N<<1]; inline void add(int u,int v,LL w) { e[++cnt].to = v,e[cnt].dis = w,e[cnt].next = head[u],head[u] = cnt; } void dfs(int u,int fa) { dep[u] = dep[fa]+1; f[++tot][0] = u; dfn[u] = tot; for(rg int i = head[u];i;i = e[i].next) { if(e[i].to == fa) continue; way[e[i].to] = way[u]+e[i].dis; dfs(e[i].to,u); f[++tot][0] = u; } } void init() { lg[1] = 0;for(rg int i = 2;i <= tot;++i) lg[i] = lg[i>>1]+1; for(rg int j = 1;j <= 19;++j) { for(rg int i = 1;i+(1<<j)-1 <= tot;++i) { if(dep[f[i][j-1]] <= dep[f[i+(1<<j-1)][j-1]]) f[i][j] = f[i][j-1]; else f[i][j] = f[i+(1<<j-1)][j-1]; } } } int LCA(int x,int y) { x = dfn[x],y = dfn[y]; if(x > y) swap(x,y); int k = lg[y-x+1]; if(dep[f[x][k]] < dep[f[y-(1<<k)+1][k]]) return f[x][k]; return f[y-(1<<k)+1][k]; } LL dis(int x,int y) { return way[x]+way[y]-2LL*way[LCA(x,y)]; } pii check(pii a,pii b) { LL ma1 = dis(a.first,b.first); LL ma2 = dis(a.first,b.second); LL ma3 = dis(a.second,b.first); LL ma4 = dis(a.second,b.second); LL ma5 = dis(a.first,a.second); LL ma6 = dis(b.first,b.second); if(ma1 >= ma2 && ma1 >= ma3 && ma1 >= ma4 && ma1 >= ma5 && ma1 >= ma6) return pii{a.first,b.first}; if(ma2 >= ma1 && ma2 >= ma3 && ma2 >= ma4 && ma2 >= ma5 && ma2 >= ma6) return pii{a.first,b.second}; if(ma3 >= ma1 && ma3 >= ma2 && ma3 >= ma4 && ma3 >= ma5 && ma3 >= ma6) return pii{a.second,b.first}; if(ma4 >= ma1 && ma4 >= ma2 && ma4 >= ma3 && ma4 >= ma5 && ma4 >= ma6) return pii{a.second,b.second}; if(ma5 >= ma1 && ma5 >= ma2 && ma5 >= ma3 && ma5 >= ma4 && ma5 >= ma6) return pii{a.first,a.second}; return pii{b.first,b.second}; } void pre() { for(rg int i = 1;i <= n;++i) st[i][0] = pii{i,i}; for(rg int j = 1;j <= 19;++j) { for(rg int i = 1;i+(1<<j)-1 <= n;++i) { st[i][j] = check(st[i][j-1],st[i+(1<<(j-1))][j-1]); } } } LL query(int x,int y) { int k = lg[y-x+1]; pii ma = check(st[x][k],st[y-(1<<k)+1][k]); return dis(ma.first,ma.second); } int main() { n = read(),q = read(); for(rg int i = 1;i < n;++i) { int u,v,w;u = read(),v = read(),w = read(); add(u,v,w);add(v,u,w); } dfs(1,0); init(); pre(); while(q--) { int L,r;L = read(),r = read(); printf("%lld\n",query(L,r)); } system("pause"); return 0; }