BZOJ 4815: [Cqoi2017]小Q的表格

Description

\(b×f(a,a+b)=(a+b)*f(a,b)\),支持修改

求\(\sum_{i=1}^k\sum_{j=1}^kf(i,j)\)

\(m\leqslant 10^4,k\leqslant n\leqslant 4\times 10^6\)

Solution

数论+分块

可以发现这是一个类似于更相减损的东西...
就是修改一个位置,只会影响与他横纵坐标相同的位置...所以它其实是一个一维的东西...
所以就是求\(\sum_{i=1}^k\sum_{j=1}^k\frac{f[(i,j)]*(i,j)^2}{ij}\)

求这个东西可以数论的分块...维护就是普通的分块...

Code

/**************************************************************
    Problem: 4815
    User: BeiYu
    Language: C++
    Result: Accepted
    Time:17544 ms
    Memory:188816 kb
****************************************************************/

#include <bits/stdc++.h>
using namespace std;

typedef long long LL;
const int N = 4e6+500;
const int B = 2000;
const LL p = 1000000007;

inline LL in(LL x=0,char ch=getchar()) { while(ch>‘9‘||ch<‘0‘) ch=getchar();
    while(ch>=‘0‘&&ch<=‘9‘)x=x*10+ch-‘0‘,ch=getchar();return x; }
void Add(LL &x,LL y) { x=(x+y)%p; }
LL Pow(LL a,LL b,LL r=1) { for(;b;b>>=1,a=a*a%p) if(b&1) r=r*a%p;return r; }

LL n,m,ans,inv_6=Pow(6,p-2);
LL f[N],g[N];
int pr[N],cp,b[N],phi[N];
int tb,bl[N],ll[N],rr[N];
LL tg[N];

void pre(int n) {
    for(int i=2;i<=n;i++) {
        if(!b[i]) pr[++cp]=i,phi[i]=i-1;
        for(int j=1;j<=cp && (LL)i*pr[j]<=n;j++) {
            b[i*pr[j]]=1;
            if(i%pr[j]) phi[i*pr[j]]=phi[i]*(pr[j]-1);
            else { phi[i*pr[j]]=phi[i]*pr[j];break; }
        }
    }phi[1]=1;
    for(int i=1;i<=n;i++) g[i]=(1LL*phi[i]*i%p*i%p+g[i-1])%p;
}

LL get_s1(LL n) { return (n*(n+1)/2)%p; }
LL get_s2(LL n) { return n*(n+1)%p*(2*n+1)%p*inv_6%p; }

void Mot(int x,LL v) {
    for(int i=x;i<=rr[bl[x]];i++) Add(f[i],v);
    for(int i=bl[x]+1;i<=tb;i++) Add(tg[i],v);
}
LL Qur(int x) { return (f[x]+tg[bl[x]])%p; }
LL A(int n) {
    LL res=0;
    for(int i=1,j;i<=n;i=j+1) {
        j=n/(n/i);
        Add(res,(Qur(j)-Qur(i-1)+p)%p*g[n/i]%p);
    }return res;
}

int main() {
    m=in(),n=in();

    pre(n);
    for(int i=1;i<=n;i++) f[i]=(1LL*i*i%p+f[i-1])%p;
    for(int i=1;i<=n;i+=B) {
        tb++,ll[tb]=i,rr[tb]=min((LL)i+B-1,n);
        for(int j=0;j<B && i+j<=n;j++) bl[i+j]=tb;
    }

    for(int i=1;i<=m;i++) {
        LL x=in(),y=in(),z=in(),k=in(),w=__gcd(x,y);
        z=z/(x/w)/(y/w)%p;
        Mot(w,(z-(f[w]-f[w-1]+p)%p+p)%p);
        printf("%lld\n",A(k));
    }return 0;
}

  

时间: 2024-10-22 21:59:27

BZOJ 4815: [Cqoi2017]小Q的表格的相关文章

[bzoj4815] [洛谷P3700] [Cqoi2017] 小Q的表格

Description 小Q是个程序员. 作为一个年轻的程序员,小Q总是被老C欺负,老C经常把一些麻烦的任务交给小Q来处理. 每当小Q不知道如何解决时,就只好向你求助.为了完成任务,小Q需要列一个表格,表格 有无穷多行,无穷多列,行和列都从1开始标号.为了完成任务,表格里面每个格子都填了 一个整数,为了方便描述,小Q把第a行第b列的整数记为f(a,b),为了完成任务,这个表格要 满足一些条件: (1)对任意的正整数a,b,都要满足f(a,b)=f(b,a): (2)对任意的正整数a,b,都要 满

bzoj4815 [Cqoi2017]小Q的表格

传送门 这题好妙啊,我好菜啊--居然连辗转相减都看不出来,我是不是没救了-- -- 考虑题目给出的两个条件: $f_{a,b}=f_{b,a}$,这个就是对称性. $b×f_{a,a+b}=(a+b)×f_{a,b}$,这个有点意思.整道题明明就是这里最难好嘛 先不管两个$f_{a,b}$之间到底有什么数量关系,只考虑哪些$f_{a,b}$互相影响,记$a~b$表示$a$与$b$相关,可以把它变形一下得到$f_{a,b}~f_{a,b-a}(a\le b)$,结合$f_{a,b}=f_{a,b}

bzoj 4814: [Cqoi2017]小Q的草稿【计算几何】

//先打个50暴力,10min50分简直美滋滋~ #include<iostream> #include<cstdio> #include<algorithm> using namespace std; const int N=5005; const double eps=1e-8; int n,t,m,ans; struct dian { double x,y; dian(double X=0,double Y=0) { x=X,y=Y; } dian operato

[CQOI2017]小Q的表格——反演好题

zhoutb2333的题解 难得一见的新颖反演题. 一眼看可能不是反演题. 修改影响别的,很恶心. 所以考虑化简f的联系式,发现和gcd有关 于是考虑用gcd来表示所有的gcd(a,b)=g的所有f(a,b)于是二维利用结合律变成了一维的问题. 修改(a,b)本质上是修改f(g,g),因为其他的数用f(g,g)表示,都在式子里. 支持单点修改,带入k询问这个函数的值. 已经可以O(根号)查一次. 对于式子反演, 单点修改,要支持区间和(前缀和)维护. 树状数组轻而易举,但是查询有logn 然后m

bzoj4814: [Cqoi2017]小Q的草稿

Description 小Q是个程序员.众所周知,程序员在写程序的时候经常需要草稿纸.小Q现在需要一张草稿纸用来画图,但是桌上 只有一张草稿纸,而且是一张被用过很多次的草稿纸.草稿纸可以看作一个二维平面,小Q甚至已经给它建立了直 角坐标系.以前每一次草稿使用过的区域,都可以近似的看作一个平面上的一个三角形,这个三角形区域的内部和 边界都不能再使用.当然了,以前的草稿也没有出现区域重叠的情况.小Q已经在草稿纸上画上了一些关键点,这 些关键点都在没使用过的区域.小Q想把这些关键点两两之间尽可能的用线

【bzoj4813】[Cqoi2017]小Q的棋盘 dfs+贪心

题目描述 小Q正在设计一种棋类游戏.在小Q设计的游戏中,棋子可以放在棋盘上的格点中.某些格点之间有连线,棋子只能在有连线的格点之间移动.整个棋盘上共有V个格点,编号为0,1,2-,V-1,它们是连通的,也就是说棋子从任意格点出发,总能到达所有的格点.小Q在设计棋盘时,还保证棋子从一个格点移动到另外任一格点的路径是唯一的.小Q现在想知道,当棋子从格点0出发,移动N步最多能经过多少格点.格点可以重复经过多次,但不重复计数. 输入 第一行包含2个正整数V,N,其中V表示格点总数,N表示移动步数. 接下

【BZOJ】 4813: [Cqoi2017]小Q的棋盘

题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=4813 暴力转移就好,考虑以某一个点为根的子树分为是否走回来两种情况 ${f_{i,j}}$表示已点$i$为根的子树,走了$j$步之后回到点$i$最多能经过多少个点 ${g_{i,j}}$表示已点$i$为根的子树,走了$j$步之后不管停在那个点最多能经过多少个点 写了个${n^{2}}$转移 1 #include<iostream> 2 #include<algorithm>

BZOJ [Cqoi2017] 小Q的棋盘

题解:枚举最后在哪里停止,然后剩下的步数/2 也就是找最大深度 枚举终止位置算是一种思路吧 #include<iostream> #include<cstdio> #include<cstring> using namespace std; const int maxn=10009; int n,m; int maxdep; int cntedge; int head[maxn]; int to[maxn<<1],nex[maxn<<1]; vo

[BZOJ4815][CQOI4815]小Q的表格 数论+分块

题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=4815 题目中所给条件中的(a,a+b)和(a,b)的关系很瞩目. 然后大家都知道(a,b)=(a,a-b)=(a,a+b),于是观察(猜)一下这个表格与gcd的关系. 可以发现每次修改(a,b)会影响到所有(i,j)=(a,b)的点,并且关系为f(i,j)=(i/a)*(j/b)*f(a,b). 所以只需要知道f(g,g)的值记为f(g),就能推出其他的值. 然后慢慢推推推大概可以推到这