【題解】CF1599F Mars

CF1599F Mars

\(\text{My blog}\)

\[\text{Solution:} \]

題目就是讓求每次詢問一個區間能否組成一個公差爲 \(d\) 的等差數列。

首先我們可以算出一個等差數列的首項——求區間和然後逆推就好了。那麼,我們如何判斷一個區間可以組成這樣一個等差數列?

考慮用一個哈希的 \(trick.\) 或者說,這個 trick 可以用來判定給定一個序列,問區間中某一個序列能否重排爲該序列 的問題。

考慮對每個元素的 \(k\) 次方之和進行 “哈希” 。如果這個數列和原數列相同,那麼其無論多少次方的和都應該是一樣的。容易發現,不同的序列面對不同的 \(k\) 的貢獻是不一樣的,所以可以這樣來判斷。

時間複雜度就取決於 \(k\) 了,實際中選擇了 \(k=\{1,2\}\) 然後套用等差數列平方求和公式即可。

別忘了取模。

#include<bits/stdc++.h>
using namespace std;
typedef double db;
#define int long long
const int mod=1e9+7;
const db eps=1e-10;
inline int Max(int x,int y){return x>y?x:y;}
inline int Min(int x,int y){return x<y?x:y;}
inline db Max(db x,db y){return x-y>eps?x:y;}
inline db Min(db x,db y){return x-y<eps?x:y;}
inline int Add(int x,int y,int M=mod){return (x+y)%M;}
inline int Mul(int x,int y,int M=mod){return 1ll*x*y%M;}
inline int Dec(int x,int y,int M=mod){return (x-y+M)%M;}
inline int Abs(int x){return x<0?-x:x;}
inline int read(){
	int s=0,w=1;
	char ch=getchar();
	while(!isdigit(ch)){if(ch=='-')w=-1;ch=getchar();}
	while(isdigit(ch)){s=s*10+ch-'0';ch=getchar();}
	return s*w;
}
inline void write(int x){
	if(x<0)putchar('-'),x=-x;
	if(x>9)write(x/10);
	putchar(x%10+'0');
}
inline int qpow(int x,int y){
	int res=1;
	while(y){
		if(y&1)res=Mul(res,x);
		x=Mul(x,x);y>>=1;
	}
	return res;
}
typedef pair<int,int> pr;
#define fi first
#define se second
#define mk make_pair
#define pb emplace_back
#define poly vector<int>
const int N=2e5+10;
int n,q,a[N];
int f[N][2],inv2,inv6;
inline int inv(int x){return qpow(x,mod-2);}
inline int sum_sq(int x){
	return Mul(inv6,Mul(x,Mul(x+1,Add(1,Mul(2,x)))));
}
inline int sum_1(int x){
	return Mul(inv2,Mul(x,x+1));
}
int calc(int og,int d,int len){
	int S2=0;
	S2=Add(S2,Mul(Mul(d,d),sum_sq(len-1)));
	S2=Add(S2,Mul(Mul(og,og),len));
	S2=Add(S2,Mul(Mul(Mul(2,d),og),sum_1(len-1)));
	return S2;
}
int calc1(int og,int d,int len){
	return Add(Mul(og,len),Mul(d,sum_1(len-1)));
}
signed main(){
	freopen("in.txt","r",stdin);
	freopen("My.out","w",stdout);
	n=read();q=read();
	for(int i=1;i<=n;++i)a[i]=read();
	for(int i=1;i<=n;++i){
		f[i][0]=Add(f[i-1][0],a[i]);
		f[i][1]=Add(f[i-1][1],Mul(a[i],a[i]));
	}
	inv2=inv(2);
	inv6=inv(6);
//	cout<<calc(2,4,1000)<<endl;
//	cout<<calc1(2,4,3)<<endl;
	int cnt=0;
	while(q--){
		++cnt;
		int l=read(),r=read(),d=read();
		if(l==r){
			puts("Yes");
			continue;
		}
		int len=(r-l+1);
		int s1=Dec(f[r][0],f[l-1][0]);
		int s2=Dec(f[r][1],f[l-1][1]);
		int og=Mul(sum_1(len-1),d);
		og=Dec(s1,og);
		og=Mul(og,inv(len));
		int S1=calc1(og,d,len);
		if(S1!=s1){
			puts("No");
			continue;
		}
		int S2=calc(og,d,len);
		if(S2!=s2){puts("No");}
		else puts("Yes");
	}
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章