一种暴力O(1)解法
这道题目看到数据都会以为是
所以直接数学方法暴力求解。
1.求解答案
首先看题目,对于任意的
令集合
由题目可得
易解得:
因此可得最大元素:
设
则答案为:
化简一下:
再考虑求
得:
显然:
也就是:
所以:
这样,我们就求出了这道题。
2.数据范围与取模
先注意数据范围,__int128 储存变量,但是会因为常数过大超时,所以我们要在计算时先确定好能被除数整除的数,先对其做除法,便可以完美的求出答案。
但注意另外一个点,求 __int128 并不支持根号运算,所以在计算时要考虑强转 long double 再存入 __int128 储存,不然会导致常数过大导致超时。
取模也是一个问题,为了节省常数复杂度,不能暴力直接全用 __int128,所以当我们除以
3.Code
展示我丑陋的代码
#include<bits/stdc++.h>
using namespace std;
typedef unsigned long long ull;
const ull md=1e9+7;
const ull ppp=500000004;
namespace Mker {
ull SA, SB, SC, p = -1;
int base;
void init(){scanf("%llu%llu%llu%d", &SA, &SB, &SC, &base); p = p << (65 - base) >> (65 - base);}
ull rand() {
ull now = SC; now += !(now & 1);
SA ^= SA << 32, SA ^= SA >> 13, SA ^= SA << 1;
ull t = SA;
return SA = SB, SB = SC, SC ^= t ^ SA, (now & p) + p + 1;
}
};
void print(__int128 x){
if(x==0)return;
print(x/10);
putchar(x%10+'0');
}
ull k;
int T;
int main(){
scanf("%d",&T); Mker::init();
while(T--){
k = Mker::rand();
ull p=(sqrt((long double)4*k-3)+1)/2;
__int128 ans;
ull a=p-1,b=p,c=2*p-1;
if(a%3==0)a/=3;
else if(b%3==0)b/=3;
else c/=3;
if(a%2==0)a/=2;
else if(b%2==0)b/=2;
else c/=2;
ans=(__int128)a*b%md*c%md;
p%=md;
ull len=(k%md*ppp%md-(((p*p%md-p%md)+md)%md+1)%md*ppp%md+md+1)%md;
p%=md;
(ans+=len*p%md)%=md;
print(ans);
putchar('\n');
}
}