fxtoi 小胖的蚊子


题面传送门
题解:逐个分析。
对于\(ans=\frac{1}{1-ans}\),考虑一下\(\%3\)分类讨论。
对于\(\%3=1\),\(answer=\frac{1}{1-ans}\)
对于\(\%3=2\),\(answer=\frac{ans-1}{ans}\)
对于\(\%3=0\),\(answer=ans\)
那么就可以直接算了。
思路出处:\(hl\)的数论。
对于\(a_i=\sum\limits_{j=1}^{i}{f_j(i-j+1)(i-j+2)\%1039}\)考虑前缀和。
做一遍前缀和,得到\(a_i=\sum\limits_{j=1}^{i}{f_j\%1039}\)
再做一遍前缀和,即得到\(a_i=\sum\limits_{j=1}^{i}{f_j(i-j+1)(i-j+2)\%1039}\)
思路出处:高阶前缀和。
对于\(a_i=\sum\limits_{i=1}^{n}{\sum\limits_{j=1}^{n}{\sum\limits_{k=1}^{n}{1[i+j+k=n]}}}\)
解法一:插空法,想象\(n\)个数之间有\(n-1\)个空格,插两块板,则方案数为\(C_{2}^{n-1}\),即\(\frac{(n-1)(n-2)}{2}\)
解法二:利用取整特性
我们发现,只有当时\(k=n-i-j\)才有值\([i+j+k=n]\)为1,所以可以优化成\(a_i=\sum\limits_{i=1}^{n-2}{\sum\limits_{j=1}^{n-i-1}{1}}\)然后我们发现我们在做一件很傻\(x\)的事:用循环模拟加法,所以可以进一步优化为\(a_i=\sum\limits_{i=1}^{n-2}{n-i-1}\),然后对于每一个\(n-i-1\)其为等差数列,于是可以转化为\(\frac{(n-1)(n-2)}{2}\)
思路出处:自己想的。
对于\(gcd(FBI(i),FBI(j))\),没啥好说的,斐波那契的性质:\(FBI(k)=gcd(FBI(ik),FBI(jk))\),其中\(i\)\(j\)互质。
对于\(b_{x,y}\)\(b_{y,y}\),因为\(b\)数组不会修改,所以用前缀和维护。
对于\(a_x\)\(a_y\),因为\(a\)数组要修改,所以用线段树维护区间最大值。
代码实现:

#include
#define min(a,b) ((a)<(b)?(a):(b))
using namespace std;
int a[1039],b[1039][1039],n,m,f[1039],x,y,c,d,s[1039]={0,1,1},z,fs[1039][1039],now,sum[10039],ans[10039],tot;
long long pus;
inline int gcd(int x,int y){
	if(!y) return x;
	return gcd(y,x%y);
}
inline void read(int &x){
	char s=getchar(); x=0;
	while(s<'0'||s>'9') s=getchar();
	while(s>='0'&&s<='9') x=(x<<3)+(x<<1)+(s^48),s=getchar();
}
inline int max(int x,int y){return x=r) return sum[now]=f[l];
    int m=(l+r)>>1;
    return sum[now]=max(jianshu(now<<1,l,m),jianshu(now<<1|1,m+1,r));
}
inline void push(int l,int r,int now){
    int m=(l+r)>>1;
    ans[now<<1]+=ans[now];
    sum[now<<1]+=ans[now];
    ans[now<<1|1]+=ans[now];
    sum[now<<1|1]+=ans[now];
    ans[now]=0;
}
inline void get(int l, int r,int now){
    if(c<=l&&d>=r){
        ans[now]-=z;
        sum[now]-=z;
        return;
    }
    int m=(l+r)>>1;
    push(l,r,now);
    if(c<=m) get(l,m,now<<1);
    if(d>m) get(m+1,r,now<<1|1);
    sum[now]=max(sum[now<<1],sum[now<<1|1]);
    return;
}
inline int  find(int l,int r,int now){
    if(x<=l&&y>=r)return sum[now];
    int m=(l+r)>>1,fs=0;
    push(l,r,now);
    if(x<=m) fs=max(find(l,m,now<<1),fs);
    if(y>m) fs=max(find(m+1,r,now<<1|1),fs);
    return fs;
}
int main(){
//	freopen("mosquito20.in","r",stdin);
//	freopen("mosquito20.out","w",stdout);
	register int i,j;
	scanf("%d%d",&n,&m);
	for(i=1;i<=n;i++) read(f[i]);
	for(i=1;i<=n;i++) f[i]=(f[i-1]+f[i])%1039;
	for(i=1;i<=n;i++) f[i]=(f[i-1]+f[i])%1039;
	for(i=1;i<=n;i++) f[i]=(f[i-1]+f[i])%1039;
	for(i=1;i<=n;i++) f[i]=min(f[i],((i*i-3*i)/2+1)%1039+2);
	for(i=3;i<=n;i++) s[i]=(s[i-1]+s[i-2])%1039;
	for(i=1;i<=n;i++){
		for(j=1;j<=n;j++){
			b[i][j]=f[i]+f[j]+s[gcd(i,j)];
		}
	}
	for(i=1;i<=n;i++){
		for(j=1;j<=n;j++) fs[i][j]=fs[i-1][j]+fs[i][j-1]-fs[i-1][j-1]+b[i][j];
	}
	jianshu(1,1,n);
	for(i=1;i<=m;i++){
		read(x);read(y);read(c);read(d);
		z=find(1,n,1);
		if((y-x+1)%3==1) z=(int)(1.0/(1.0-z)*139)%1039;
		else if((y-x+1)%3==2) z=(int)((z-1)*1.0/z*139)%1039;
		else z=z*139%1039;
		tot=fs[y][y]-fs[x-1][y]-fs[y][x-1]+fs[x-1][x-1];
		pus+=max(0,z-tot);
		get(1,n,1);
	}
	printf("%lld",pus);
}