中国农业建设网站,阳春房产网,中国最好的品牌策划公司,商业空间设计心得体会正题
题目链接:http://codeforces.com/contest/1603/problem/C 题目大意
定义一个序列aaa的f(a)f(a)f(a)为你每次可以将序列中的一个数zzz分裂成xyzxyzxyz#xff0c;然后再把x,yx,yx,y放回原来的位置#xff0c;然后f(a)f(a)f(a)表示把aaa变成不降序列的最少操作次数 给出…正题
题目链接:http://codeforces.com/contest/1603/problem/C 题目大意
定义一个序列aaa的f(a)f(a)f(a)为你每次可以将序列中的一个数zzz分裂成xyzxyzxyz然后再把x,yx,yx,y放回原来的位置然后f(a)f(a)f(a)表示把aaa变成不降序列的最少操作次数 给出一个长度为nnn的序列aaa求它所有子区间的fff值的和。
1≤n,ai≤1051\leq n,a_i\leq 10^51≤n,ai≤105 解题思路
显然的每个数字aia_iai最终肯定是分解为k−1k-1k−1个⌊aik⌋\lfloor\frac{a_i}{k}\rfloor⌊kai⌋和一个⌈aik⌉\lceil\frac{a_i}{k}\rceil⌈kai⌉。 然后我们对于一个序列可以从右往左每个选择能分解的最小的次数来分肯定是最优的。 那么考虑暴力的dpdpdp设fi,jf_{i,j}fi,j表示现在第iii个所有左端点为iii的区间中aia_iai分解的最前面那个为kkk的方案然后倒着转移就好了。 考虑到jjj肯定是某个⌊aik⌋\lfloor\frac{a_i}{k}\rfloor⌊kai⌋而⌊aik⌋\lfloor\frac{a_i}{k}\rfloor⌊kai⌋最多只有2ai2\sqrt a_i2ai种取值所以我们可以只枚举这些取值就好了。
时间复杂度O(nai)O(n\sqrt a_i)O(nai)略微卡常 code
#includecstdio
#includecstring
#includealgorithm
#define ll long long
using namespace std;
const ll N1e510,P998244353;
ll T,n,ans,a[N],f[2][N],g[2][N];
signed main()
{scanf(%lld,T);while(T--){scanf(%lld,n);for(ll i1;in;i)scanf(%lld,a[i]);ll o0;g[o][a[n]]1;ans0;for(ll in-1;i1;i--){o^1;ll ma[i1];for(ll l1,r;lm;lr1){rm/(m/l);ll xm/l,w(a[i]x-1)/x,ka[i]/w;f[o][k]f[!o][x](w-1)*g[!o][x];g[o][k]g[!o][x];ansf[!o][x];ans%P;f[!o][x]g[!o][x]0;}g[o][a[i]];}for(ll l1,r;la[1];lr1)ra[1]/(a[1]/l),(ansf[o][a[1]/l])%P,f[o][a[1]/l]g[o][a[1]/l]0;printf(%lld\n,ans);}return 0;
}