Gym101620C Cumulative Code

Link
memory search.
The search state is set to \ ((n-, K, now, FLG) \) , represents the depth of \ (n-\) , existing \ (K \) bits Prüfer Code, the remaining \ (now \) that needs to be calculated position, if there is a parent edge.
If the current point \ (X \) , then the answer will be labeled as a ternary structure \ ((A, B, C) \) , represents the answer is \ (ax + b + c \ lfloor \ frac x2 \ rfloor \) .
The answer to the current set point \ ((A, b, c) \) , son of the answer is \ ((A, B, C) \) , to consider how to merge.
Son Left: \ (A \ LeftArrow. 2A + A + C, B \ LeftArrow B + B \) .
Right Son: \ (A \ LeftArrow. 2A + A + C, B \ LeftArrow B + A + B \) .
Then consider optimizing memory utilization of time complexity.
Only when the first sub-tree corresponding to the number Prüfer Code \ ([A, A + (. 1-m) D] \) , and the subtree of the parent only for memory side.
We set memory status\ (f_ {k, i} \) represents the root node as \ (X \) , a depth of \ (K \) , and any \ (p '_ {i + jd} \) is the point of the answer needs to be computed the answer to \ (f_ {k, i} \) answers represented by the structure ( \ (P '= \ {p'_n \} \) is the subtree Prüfer Code).
Because all sides have a depth of parent \ (k \) in order to delete a full binary tree is constant, so the only answer to this part of the related offset the first to be selected point in the sub-tree Prüfer Code.
We only record \ (k \ le 15 \) state, so that the time complexity for a single search \ (2 ^ {\ FRAC K2} \) .

#include<cstdio>
#include<algorithm>
using i64=long long;
int read(){int x;scanf("%d",&x);return x;}
const int N=17,M=32768;
struct node
{
    i64 a,b,c;
    node(i64 A=0,i64 B=0,i64 C=0):a(A),b(B),c(C){};
    void mergel(node x){a+=x.a+x.a+x.c,b+=x.b;}
    void merger(node x){a+=x.a+x.a+x.c,b+=x.a+x.b;}
}f[N][M];
int st,d,m,ed,num,id[N][M];
node dfs(int n,int k,int now,int flg)
{
    if(now<=0) return node();
    int p=((st-k)%d+d)%d,size,pos;node ans;
    if(!p) p=d;
    p=std::max(p,st-k);
    if(p>=1<<n) return node();
    if(n<=1) return node(0,0,1);
    if(n<=15&&flg&&k+1>=st&&k+(1<<n)-1<=ed&&id[n][p]==num) return f[n][p];
    if(p<=(1<<(n-1))-1) size=(std::min(ed-k,(1<<(n-1))-1)-p)/d+1,ans.mergel(dfs(n-1,k,size,1)),now-=size;
    if(!flg) if(pos=k+(1<<(n-1)),!((pos-st)%d)&&st<=pos&&pos<=ed) ans.a+=2,++ans.b,--now;
    if(now>0) pos=k+(1<<n)-1,ans.merger(dfs(n-1,k+(1<<(n-1))-flg,now-(flg&&!((pos-st)%d)&&st<=pos&&pos<=ed),flg));
    if(flg) if(pos=k+(1<<n)-1,!((pos-st)%d)&&st<=pos&&pos<=ed) ++ans.c;
    if(n<=15&&flg&&k+1>=st&&k+(1<<n)-1<=ed) id[n][p]=num,f[n][p]=ans;
    return ans;
}

int main()
{
    for(int dep=read(),Q=read();Q;--Q)
    {
	++num,st=read(),d=read(),m=read(),ed=st+d*(m-1);
	node ans=dfs(dep,0,m,0);printf("%lld\n",ans.a+ans.b);
    }
}

Guess you like

Origin www.cnblogs.com/cjoierShiina-Mashiro/p/12602811.html