A.简单题
不难发现,题目中的\(P\)是没有用的,然而好像并没有什么用,题目可以转化为,有两个数\(a\)(题目中的\(a+b\))和\(b\)(题目中的\(c\)),如果\(a>b\),那么\(a=a-b\),\(b=b*2\),否则\(a=a*2\),\(b=b-a\),再看几眼就会发现\(a+b\)是一个定值,这里设为\(sum\),目前的转移有两种情况
case#1:\(b=b*2\);
case#2:\(b=b-a\);
对于第一种情况\(b<a\),\(b\)就变成了\(b*2\);
对于第二种情况\(b>=a\),因为\(a+b=sum\),所以\(a-b+2*b=sum\),所以\(2*b-sum=b-a\),因为\(b>=a\)且\(a+b=sum\),所以\(sum/2<=b<=sum\),所以\(sum<=2*b<=2*sum\),所以有\(2*b%sum=b-a\),所以\(b\)变成了\(b*2%sum\);
对于第一种情况,\(b<a\),所以\(b<sum/2\),所以\(2*b<sum\),所以\(b*2%sum=b*2\),所以对于每一次操作其实都是\(b*2%sum\),所以答案就是\(qpow(2,k,sum)*b%sum\);
B.斗地主
我们将每一张牌的两面连边,不难发现如果一个联通块是树(边数=点数-1)肯定这个联通块不能全部选到,否则(边数>=点数)都有方案使联通块中的所有点都选到,然后来考虑这个题,对于一个顺子的起点,右端点显然是满足单调性的,双指针处理一下所有的答案就可以了,下面是核心代码,c代表该联通块当前已经选了的点数,size带便该联通块的边数,在\(c[fj]<size[fj]\)的情况下加入该点,指针右移,统计答案就可以了
for(int i=1,j=1,fj;i<=n;ans[i]=j-1,c[find_root(i)]--,i++)while(j<=n&&(fj=find_root(j))&&c[fj]<size[fj])c[fj]++,j++;
C.变化的树
我们考虑节点\(v\)的答案是什么, 其实就是
\(\sum ^{i-1}_{t=1}(x_t-dis[u_t,v]*k_t)\)
转化一下
\(\sum ^{i-1}_{t=1}(x_t- ( dep[u]-dep[v_t] )*k_t)\)
\(\sum ^{i-1}_{t=1}(x_t + dep[v_t]*k_t)-dep[v]*\sum ^{i-1}_{t=1}k_t\)
这样就可以维护了,但是我们发现这个东西需要满足\(u_t\)在\(1->v\)的路径上,我们可以利用\(dfs\)的性质解决决,然后这个东西直接用两个树状数组维护即可,操作只有区间加和单点查询。复杂度为\(\Theta (m log m + n)\)