[牛客2020第三场]牛半仙的妹儿数

牛半仙的妹儿数

题解

第一次在比赛中被T1(这里指应该被当做T1的题)卡绝望,赛上竟然只会O(\frac{kt}{log_{k}})的做法。

容易发现,如果我们把A+B看作一个整体的话,它是与C成规律变化的。因为在第二个操作中(A-P)+(B+P-C)= A+B-C的,P的大小不会对我们造成任何影响,于是我们可以把A+B看作一个整体,设作D。于是我们得到了下面的操作:

D\leq C时,操作变为(D,C)\rightarrow (2D,C-D)

否则,操作变为(D,C)\rightarrow (D-C,2C)

此时,我们可以看出,D+C的值是一个定值。

于是,一个不知道如何处理转换过程的傻子出现了,竟然直接用二分去找进行多少次操作达到临界条件!

我们发现,在操作一中(2D,C-D)=(2D,2C-(C+D))=(2D,2C\, \, mod\, \, (C+D))的,而如果D\leq C的话,2C\leq C+D,于是,我们对每次操作直接乘2就行了。

于是,答案就是2^kC\, \, mod\, \, (A+B+C),直接快速幂,时间复杂度O\left(tlog_{k} \right )

源码

#include<cstdio>
#include<cmath>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<vector>
#include<queue>
#include<map>
#include<set>
using namespace std;
#define MAXN 100005
typedef long long LL;
typedef unsigned long long uLL;
typedef pair<int,int> pii;
template<typename _T>
_T Fabs(_T x){return x<0?-x:x;}
template<typename _T>
void read(_T &x){
	_T f=1;x=0;char s=getchar();
	while(s>'9'||s<'0'){if(s=='-')f=-1;s=getchar();}
	while('0'<=s&&s<='9'){x=(x<<3)+(x<<1)+(s^48);s=getchar();}
	x*=f;
}
LL t,a,b,c,k;
signed main(){
	read(t);
	while(t--){
		read(a);read(b);read(c);read(k);LL ans=c,sum=a+b+c;
        if(!k||a+b==0)printf("%lld\n",ans);
        else{
            LL d=2;
            while(k){
                if(k&1)ans=ans*d%sum;
                k>>=1;d=d*d%sum;
            }
            printf("%lld\n",ans);
        }
	}
	return 0;
}
/*

*/

谢谢!!!

posted @ 2020-10-23 19:07  StaroForgin  阅读(17)  评论(0)    收藏  举报  来源