赞
踩
阿楚姐骗我们这场只有div2A~C难度
比赛传送门
题解传送门,目前似乎没有官方题解
给你长度为 n n n的数组 a 1 … a n a_1\dots a_n a1…an,和一个整数 k k k,你必须从数组中选一个数,并将它向前移动 k k k位,使得 F ( n ) = ∑ i = 1 n i × a i F(n)=\sum_{i=1}^ni\times a_i F(n)=∑i=1ni×ai的值最大。
前缀和+枚举。
先在读入时预处理出前缀和,计算出原本的
a
a
a数组对应的
F
(
n
)
F(n)
F(n),记为
M
M
M。
当枚举到第
i
i
i位时,因为第
i
i
i位的移动使得前面的
k
k
k位向后移一位,而自身又向前移动了
k
k
k位,相对于
M
M
M产生的变化即为
−
a
i
∗
k
+
∑
j
=
i
−
k
i
−
1
a
j
-a_i*k+\sum_{j=i-k}^{i-1}a_j
−ai∗k+∑j=i−ki−1aj,记录其中的最大值即为答案
时间复杂度
O
(
n
)
O(n)
O(n)
#include<bits/stdc++.h> using namespace std; typedef long long ll; //#define int ll const int maxn=2e5+10,inf=0x3f3f3f3f,mod=1000000007; ll a[maxn],sum[maxn]; signed main() { int t,n,k; scanf("%d",&t); while(t--) { ll ans=0,ma=0; scanf("%d%d",&n,&k); for(int i=1;i<=n;i++) { scanf("%lld",&a[i]); sum[i]=sum[i-1]+a[i]; ma+=i*a[i]; } for(int i=k+1;i<=n;i++) ans=max(ans,ma-a[i]*k+sum[i-1]-sum[i-k-1]); printf("%lld\n",ans); } return 0; }
这道题原题题面很坑……建议不看自己猜题意
n
n
n个人排成一竖排以速度
v
v
v跑步,正常队形中每两个人间隔为
u
u
u,每个人有超车速度
c
c
c和衰减速度
d
d
d,当一个人在队伍末尾时,此人开始以速度
c
−
(
j
−
1
)
×
d
c-(j-1)\times d
c−(j−1)×d进行超车,这里的
j
j
j表示此人是第
j
j
j个开始超车的。
现在
n
n
n个人初始位置随机,求每个人都进行一次超车所用的时间期望。
坑点:当上一个人还在超车过程中,当前队伍末尾的人是不开始超车的;而当上一个人到达了新的排头,末尾的人立即开始进行超车。
计算出每个人以每种可能的出发次序达到队首的所用时间并求和,最后除以
n
n
n,即为答案。
时间复杂度
O
(
n
2
)
O(n^2)
O(n2)
#include<bits/stdc++.h> using namespace std; typedef long long ll; //#define int ll const int maxn=1010,inf=0x3f3f3f3f,mod=1000000007; double c[maxn],d[maxn];//初始速度,每轮衰减量 signed main() { int n; double v,u,ans=0; cin>>n>>v>>u;//n个人,间隔u米,每个人速度均为v for(int i=1;i<=n;i++) cin>>c[i]; for(int i=1;i<=n;i++) cin>>d[i]; for(int i=1;i<=n;i++) {//第i个人以第j位出发所用时间 for(int j=1;j<=n;j++) {//此人相对于队伍的速度 ans+=n*u/(c[i]-(j-1)*d[i]-v); } } cout<<setiosflags(ios::fixed)<<setprecision(3)<<ans/n<<endl; return 0; }
一棵 n n n个节点的树, 1 1 1为树的根节点, q q q个询问,每个询问三个数字 a , b , c a,b,c a,b,c,表示
很明显这是个LCA的题,符合题意的情况有两种
记
d
1
d1
d1为老师到
1
1
1节点的路程,
d
2
d2
d2为同学先到
c
c
c再到
1
1
1行走的路程。
注意:多组输入,不用
m
e
m
s
e
t
memset
memset见祖宗
单组时间复杂度
O
(
n
+
q
l
o
g
n
)
O(n+qlogn)
O(n+qlogn)
#include<bits/stdc++.h> using namespace std; typedef long long ll; //#define int ll const int maxn=2e5+10,inf=0x3f3f3f3f,mod=1000000007; void read(){} template<typename T,typename... T2>inline void read(T &x,T2 &... oth) { x=0; int ch=getchar(),f=0; while(ch<'0'||ch>'9'){if (ch=='-') f=1;ch=getchar();} while (ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();} if(f)x=-x; read(oth...); } const int maxl=30; vector<int> G[maxn];//无权边,也可以选择链式前向星存图 int gene[maxn][maxl],depth[maxn],lg[maxn]; //int nodes[maxn];//子树结点的数量 void dfs(int x,int fa) { depth[x]=depth[fa]+1; gene[x][0]=fa; // nodes[x]=1; for(int i=1;(1<<i)<=depth[x];i++)//倍增 gene[x][i]=gene[gene[x][i-1]][i-1]; for(int i=0;i<G[x].size();i++) if(G[x][i]!=fa) { dfs(G[x][i],x);//在dfs前后加语句可以求出许多有趣的东西 // nodes[x]+=nodes[G[x][i]]; } } int lca(int x,int y) { if(depth[x]<depth[y])//保证x深度≥y swap(x,y); while(depth[x]>depth[y])//将x提到同一高度 x=gene[x][lg[depth[x]-depth[y]-1]]; if(x==y)//是同一个节点 return x; for(int i=lg[depth[x]];i>=0;i--) if(gene[x][i]!=gene[y][i]) {//二分思想,直到跳到LCA的下面一层 x=gene[x][i]; y=gene[y][i]; } return gene[x][0]; } int dist(int x,int y)//x节点到y结点的距离 { int tem=lca(x,y); return (int)(abs(depth[x]-depth[tem])+abs(depth[y]-depth[tem])); } void init(int s,int n) { memset(gene,0,sizeof(gene)); depth[s]=0; for(int i=1;i<=n;i++)//预处理出log2(i)+1的值 lg[i]=lg[i-1]+((1<<(lg[i-1]+1))==i);//不要写错 dfs(s,0); } signed main() { std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0); #ifdef DEBUG freopen("input.in", "r", stdin); // freopen("output.out", "w", stdout); #endif int t,n,u,v,q; read(t); while(t--) { read(n,q); for(int i=1;i<=n;i++) G[i].clear(); for(int i=1;i<n;i++) { read(u,v); G[u].push_back(v); G[v].push_back(u); } init(1,n); int a,b,c; while(q--) { read(a,b,c); bool ok=0; int t=dist(a,1),sk=dist(b,c)+dist(c,1); if(t<sk||(t==sk&&lca(c,a)!=1)) ok=1; printf("%s\n",(ok?"YES":"NO")); } } return 0; }
定义一个数字为幸运数字当且仅当它的所有数位都是4或者7。
比如47、744、4都是幸运数字而5、17、467都不是。
定义
n
e
x
t
(
x
)
next(x)
next(x)为大于等于
x
x
x的第一个幸运数字。
给定
l
,
r
l,r
l,r,求出
n
e
x
t
(
l
)
+
n
e
x
t
(
l
+
1
)
+
.
.
.
+
n
e
x
t
(
r
−
1
)
+
n
e
x
t
(
r
)
next(l) + next(l + 1) + ... + next(r - 1) + next(r)
next(l)+next(l+1)+...+next(r−1)+next(r)。
使用dfs枚举构造出所有幸运数字,排序后在数组中二分查找当前数字的幸运数字
时间复杂度估计为
O
(
2
10
+
10
×
2
10
+
10
×
l
o
g
10
r
−
l
)
O(2^{10}+10\times 2^{10}+10\times log_{10}^{r-l})
O(210+10×210+10×log10r−l)?
#include<bits/stdc++.h> using namespace std; typedef long long ll; //#define int ll const int maxn=2e5+10,inf=0x3f3f3f3f,mod=1000000007; vector<ll>luck; void dfs(ll x) { if(x>5e9) return; luck.push_back(x); dfs(x*10+4); dfs(x*10+7); } signed main() { dfs(0); sort(luck.begin(),luck.end()); ll l,r,ans=0; cin>>l>>r; while(l<=r) { ll nex=*lower_bound(luck.begin(),luck.end(),l); if(nex>=r) { ans+=(r-l+1)*nex; break; } ans+=(nex-l+1)*nex; l=nex+1; } cout<<ans<<endl; return 0; }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。