CF2038B Make It Equal 线性题解
这是一个线性做法。
设
设最后所有的数为
先将
也就是答案等于
接下来尝试解方程组,将第
也就是
显然不可能存下来
考虑取模,取两个大质数
我们断言
然后我们则有
记为
代入
代入
复杂度线性。
放个代码:
:::info[code]
#include <bits/stdc++.h>
using namespace std;
using ll=long long;
using ull=unsigned long long;
using pii=pair<int,int>;
template<typename tp> inline void cmin(tp &a,tp b){(b<a)&&(a=b);}
template<typename tp> inline void cmax(tp &a,tp b){(b>a)&&(a=b);}
template<typename tp> inline tp pmin(tp a,tp b){return a<b?a:b;}
template<typename tp> inline tp pmax(tp a,tp b){return a<b?a:b;}
template<typename tp>
inline void read(tp &x){
tp f=1;x=0;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
while(isdigit(ch)){x=x*10+(ch^48);ch=getchar();}
x*=f;
}
template<typename tp>
inline void write(tp x,char ed=' '){
static char stk[40];
int top=0;
if(x<0) putchar('-'),x=-x;
do stk[++top]=x%10+48,x/=10; while(x);
while(top) putchar(stk[top--]);
putchar(ed);
}
constexpr unsigned mod1=1'000'000'007,mod2=1'000'000'009;
template<unsigned mod>
unsigned fpow(unsigned x,int p){
unsigned res=1;
while(p){
if(p&1) res=1ull*res*x%mod;
x=1ull*x*x%mod;
p>>=1;
}
return res;
}
void mian(){
int n;
read(n);
vector<unsigned> a(n+1);
unsigned lam1=0,lam2=0;
unsigned pw1=1,pw2=1;
for(int i=1;i<=n;i++){
read(a[i]);
lam1+=1ull*a[i]*pw1%mod1;
(lam1>=mod1)&&(lam1-=mod1);
lam2+=1ull*a[i]*pw2%mod2;
(lam2>=mod2)&&(lam2-=mod2);
pw1*=2;
(pw1>=mod1)&&(pw1-=mod1);
pw2*=2;
(pw2>=mod2)&&(pw2-=mod2);
}
pw1--;
if(pw1>mod1) pw1=mod1-1;
pw2--;
if(pw2>mod2) pw1=mod2-1;
unsigned inv1=fpow<mod1>(pw1,mod1-2),inv2=fpow<mod2>(pw2,mod2-2);
lam1=1ull*lam1*inv1%mod1;
lam2=1ull*lam2*inv2%mod2;
if(lam1!=lam2){
puts("-1");
return;
}
vector<ll> c(n);
//b[i]=c[i]-x;
c[0]=lam1;
c[n-1]=2*c[0]-a[n];
for(int i=n-2;i>=1;i--){
c[i]=2*c[i+1]-a[i+1];
}
ll x=*min_element(c.begin(),c.end());
if(x<0){
puts("-1");
return;
}
printf("%lld\n",accumulate(a.begin()+1,a.end(),0ll)-1ll*n*x);
}
int main(){
int _T;
read(_T);
while(_T--) mian();
return 0;
}
:::