A - Arithmetic Progression
给你A,B,D,输出A,A+D,A+2*D,...到B为止,一个循环就可以解决。
#include <bits/stdc++.h>
//#define int long long
#define per(i,j,k) for(int (i)=(j);(i)<=(k);++(i))
#define rep(i,j,k) for(int (i)=(j);(i)>=(k);--(i))
#define fr first
#define se second
#define endl '\n'
using namespace std;
int a,b,d;
void solve(){
cin>>a>>b>>d;
for(int i=a;i<=b;i+=d)cout<<i<<" ";
}
signed main(){
ios::sync_with_stdio(false),cin.tie(nullptr);
int t=1;
while(t--)solve();
return 0;
}
B - Append
输入1,往序列后面添加x。
输入2,查询从后往前第k个数。
可以用数组模拟扩展,也可以用vector直接来做。
#include <bits/stdc++.h>
//#define int long long
#define per(i,j,k) for(int (i)=(j);(i)<=(k);++(i))
#define rep(i,j,k) for(int (i)=(j);(i)>=(k);--(i))
#define fr first
#define se second
#define endl '\n'
using namespace std;
int q,opt,x,k;
vector<int>a;
void solve(){
cin>>q;
while(q--){
cin>>opt;
if(opt==1){
cin>>x;
a.push_back(x);
}else if(opt==2){
cin>>k;
cout<<a[a.size()-k]<<endl;
}
}
}
signed main(){
ios::sync_with_stdio(false),cin.tie(nullptr);
int t=1;
while(t--)solve();
return 0;
}
补题:C - Divide and Divide
给你一个数N,写在黑板上。对黑板上大于等于2的执行操作,设其为x,擦除x(答案就是擦除的总数),写上x/2向下取整和x/2向上取整。
N<=1e17,数组开不下的话只能动态dp或者记忆化搜索,因为下面的正常搜索写出来测试了大概10秒钟也不出答案,那复杂度就超了,想办法剪枝或者记忆重复搜索的内容。
void dfs(int x){
if(x<2)return;
ans+=x;
if(x%2==1)dfs(x>>1),dfs(x/2+1);
else dfs(x>>1),dfs(x>>1);
}
因为是递归(相当于调用函数,两个dfs的值是一样的),所以dfs(x>>1)可以先算出来一个,然后直接乘以二。
int dfs(int x){
if(x<2)return 0;
if(x&1){
return dfs(x>>1)+dfs((x>>1)+1)+x;
}else{
return dfs(x>>1)*2+x;
}
}
但是这么写还是过不了,1e17进去能过,但是1e17-1,奇数进去刚好超时一点点。再结合递归性质,一大堆递归都是先放好不执行,一条路走到底再去走别的,所以可以加一个map记录计算过的数。
map<int,int>f;
int dfs(int x){
if(x<2)return 0;
if(f[x])return f[x];
if(x&1){
return dfs(x>>1)+dfs((x>>1)+1)+x;
}else{
return f[x]=dfs(x>>1)*2+x;
}
}
这样就可以1msAC了!
完整代码
#include <bits/stdc++.h>
#define int long long
#define per(i,j,k) for(int (i)=(j);(i)<=(k);++(i))
#define rep(i,j,k) for(int (i)=(j);(i)>=(k);--(i))
#define fr first
#define se second
#define endl '\n'
using namespace std;
int n;
map<int,int>f;
int dfs(int x){
if(x<2)return 0;
if(f[x])return f[x];
if(x&1){
return dfs(x>>1)+dfs((x>>1)+1)+x;
}else{
return f[x]=dfs(x>>1)*2+x;
}
}
void solve(){
cin>>n;
cout<<dfs(n);
}
signed main(){
ios::sync_with_stdio(false),cin.tie(nullptr);
int t=1;
while(t--)solve();
return 0;
}
D - Super Takahashi Bros.
题目应该是比较容易读懂的,每一个舞台都可以花费A[i]到达下一个舞台,或者花费B[i]到达X[i]舞台。
如果只考虑当前这个点怎么做单次决策那就做不了这道题,因为X[i]会多次来回跳,所以正常的贪心和dp都做不了这道题。
舞台 i 能到 i+1 还能到 x[i],还有花费,如果能想到建图,那这道题就解决了。
因为权值都是正的,N=2e5,所以采用优先队列优化的dijkstra算法(正常的dj算法不一定能过,N*N复杂度有风险,这道题节点固定为N个,所以优先队列来优化选点更好)
#include <bits/stdc++.h>
#define int long long
#define per(i,j,k) for(int (i)=(j);(i)<=(k);++(i))
#define rep(i,j,k) for(int (i)=(j);(i)>=(k);--(i))
#define fr first
#define se second
#define endl '\n'
using namespace std;
const int N=2e5+5,MAX=LONG_LONG_MAX>>1;
int n,a,b,x,dist[N];
priority_queue<pair<int,int>,vector<pair<int,int>>,greater<pair<int,int>>>q;
vector<pair<int,int>>e[N];
bitset<N>vis;
void solve(){
cin>>n;
per(i,1,n-1){
cin>>a>>b>>x;
e[i].push_back({a,i+1});
e[i].push_back({b,x});
}
per(i,2,n)dist[i]=MAX;
q.push({0,1});
while(!q.empty()){
int now=q.top().second;
int nowDis=q.top().first;
q.pop();
if(vis[now])continue;
vis[now]=true;
for(auto i:e[now]){
int toNextLength=i.first;
int nxt=i.second;
if(dist[nxt]>dist[now]+toNextLength){
dist[nxt]=dist[now]+toNextLength;
if(!vis[nxt]){
q.push({dist[nxt],nxt});
}
}
}
}
cout<<dist[n]<<endl;
}
signed main(){
ios::sync_with_stdio(false),cin.tie(nullptr);
int t=1;
while(t--)solve();
return 0;
}
记得开longlong。