• BZOJ 4815: [Cqoi2017]小Q的表格


    推到一半被一个函数卡住真是太屑了的说(菜是原罪)

    首先对于(b imes f(a,a+b)=(a+b) imes f(a,b))我们把它化成一个整齐一点的式子:(frac{f(a,a+b)}{a(a+b)}=frac{f(a,b)}{ab})

    这样是不是看出点什么了,然后考虑(f)里的变化,是不是相当于一个数减去另一个数

    如果我们减到不能减,然后再换过来继续减,直到两数相等,容易发现此时我们相当于在进行辗转相减的过程,实际上容易发现会递归到(gcd(a,b)),因此我们有:

    [f(a,b)=frac{ab imes f(d,d)}{d^2},d=gcd(a,b) ]

    那么就意为着我们只需要考虑(f(d,d))对棋盘的影响即可,考虑对于前(n)行前(n)列的棋盘求和:

    [ans=sum_{i=1}^nsum_{j=1}^n frac{ij imes f(gcd(i,j),gcd(i,j))}{gcd(i,j)^2}\=sum_{d=1}^n frac{f(d,d)}{d^2} sum_{i=1}^nsum_{j=1}^n ij[gcd(i,j)=d]\=sum_{d=1}^n f(d,d) sum_{i=1}^{lfloorfrac{n}{d} floor}sum_{j=1}^{lfloorfrac{n}{d} floor} ij[gcd(i,j)=1]\=sum_{d=1}^n f(d,d) sum_{i=1}^{lfloorfrac{n}{d} floor}sum_{j=1}^{lfloorfrac{n}{d} floor} ijsum_{k|i,k|j}mu(k)\=sum_{d=1}^n f(d,d) sum_{k=1}^{lfloorfrac{n}{d} floor}mu(k) imes k^2 imes (sum_{i=1}^{lfloorfrac{n}{kd} floor} i) imes (sum_{j=1}^{lfloorfrac{n}{kd} floor} j)\=sum_{d=1}^n f(d,d) sum_{k=1}^{lfloorfrac{n}{d} floor}mu(k) imes k^2 imes S(lfloorfrac{n}{kd} floor)^2\ ]

    其中(S(n)=frac{n(n+1)}{2}),前面的部分可以求出前缀和然后除法分块,那么问题是后面的这部分怎么做(到这里就不会了)

    看了题解发现方法确实是妙,我们令(G(n)=sum_{i=1}^n mu(i) imes i^2 imes S(lfloorfrac{n}{i} floor)^2),发现主要是里面(S(lfloorfrac{n}{i} floor))有个下取整很难搞

    考虑运用关于下取整的技巧——差分

    [lfloorfrac{n}{i} floor-lfloorfrac{n-1}{i} floor=[i|n] ]

    然后就有:

    [G(n)-G(n-1)=sum_{i|n} mu(i) imes i^2 imes [S(lfloorfrac{n}{i} floor)^2-S(lfloorfrac{n}{i} floor-1)^2]\=sum_{i|n}mu(i) imes i^2 imes(frac{n}{i})^3\=n^2sum_{i|n}mu(i) imesfrac{n}{i}\=n^2 imes varphi(n) ]

    第二步的转化自已化开一下就出来了,最后一步的原因是(varphiast I=idLeftrightarrow varphiast Iast mu=idast muLeftrightarrow varphiast epsilon=idast muLeftrightarrowvarphi=idast mu),就进行了这一步化(mu)(varphi)

    于是(G(n))就可以(O(n))预处理了

    考虑我们还需要修改,显然每次修改都只需要修改一个对应的(f(d,d))即可,而我们同时也要维护(f(d,d))的前缀和

    如果直接用树状数组维护单次询问的复杂度达到(O(sqrt nlog n)),这样可能会被卡掉

    但是我们套路地发现这个修改的复杂度可以大一些,因为前面不需要乘(sqrt n)的询问次数,因此我们容易想到用分块(O(sqrt n))修改(O(1))询问,总复杂度就是(O(msqrt n))的了

    PS:这题不知道为什么BZOJ上一直RE,Luogu和LOJ上都没问题,下载了数据也是对的233

    #include<cstdio>
    #include<cmath>
    #define RI register int
    #define CI const int&
    using namespace std;
    const int N=4e6,mod=1e9+7;
    int n,m,a,b,k,prime[N+5],cnt,phi[N+5],g[N+5]; bool vis[N+5]; long long x;
    inline int gcd(CI x,CI y)
    {
    	return y?gcd(y,x%y):x;
    }
    inline int sum(CI x,CI y)
    {
    	int t=x+y; return t>=mod?t-mod:t;
    }
    inline int sub(CI x,CI y)
    {
    	int t=x-y; return t<0?t+mod:t;
    }
    #define P(x) prime[x]
    inline void init(CI n)
    {
    	RI i,j; for (vis[1]=phi[1]=1,i=2;i<=n;++i)
    	{
    		if (!vis[i]) prime[++cnt]=i,phi[i]=i-1;
    		int tp; for (j=1;j<=cnt&&(tp=i*P(j))<=n;++j)
    		{
    			vis[tp]=1; if (i%P(j)) phi[tp]=phi[i]*(P(j)-1);
    			else { phi[tp]=phi[i]*P(j); break; }
    		}
    	}
    	for (i=1;i<=n;++i) g[i]=sum(g[i-1],1LL*i*i%mod*phi[i]%mod);
    }
    #undef P
    class Value_Blocks
    {
    	private:
    		static const int S=2005;
    		int a[N+5],pfx[S][S],tag[S],bel[N+5],L[S],R[S],size;
    	public:
    		inline void init(CI n)
    		{
    			RI i,j; for (size=(int)sqrt(n),i=1;i<=n;++i) bel[i]=(i-1)/size+1;
    			for (i=1;i<=bel[n];++i) L[i]=(i-1)*size+1,R[i]=i*size; R[n]=n;
    			for (i=1;i<=bel[n];++i) for (j=L[i];j<=R[i];++j)
    			tag[i]=sum(tag[i],a[j]=1LL*j*j%mod),pfx[i][j-L[i]+1]=sum(pfx[i][j-L[i]],a[j]);
    			for (i=1;i<=bel[n];++i) tag[i]=sum(tag[i],tag[i-1]);
    		}
    		inline void modify(CI x,CI y)
    		{
    			RI i; int mv=sub(y,a[x]); a[x]=y;
    			for (i=x;i<=R[bel[x]];++i) pfx[bel[x]][i-L[bel[x]]+1]=sum(pfx[bel[x]][i-L[bel[x]]+1],mv);
    			for (i=bel[x];i<=bel[n];++i) tag[i]=sum(tag[i],mv);
    		}
    		inline int query(CI x)
    		{
    			//int ret=0; for (RI i=1;i<=x;++i) ret=sum(ret,a[i]); return ret;
    			return x?sum(tag[bel[x]-1],pfx[bel[x]][x-L[bel[x]]+1]):0;
    		}
    }B;
    int main()
    {
    	for (scanf("%d%d",&m,&n),init(n),B.init(n);m;--m)
    	{
    		scanf("%d%d%lld%d",&a,&b,&x,&k); int d=gcd(a,b),ans=0;
    		B.modify(d,(x/(1LL*(a/d)*(b/d)))%mod); for (RI l=1,r;l<=k;l=r+1)
    		r=k/(k/l),ans=sum(ans,1LL*sub(B.query(r),B.query(l-1))*g[k/l]%mod);
    		printf("%d
    ",ans);
    	}
    	return 0;
    }
    
  • 相关阅读:
    nginx 启用php解析及解决无法访问报错Primary script unknown的过程
    百度云服务器连接码云的坑
    async函数测试
    centos6.8安装mysql5.7及用navicat远程连接
    JavaScript模块知识理解
    为什么if else 语句里不能用函数声明定义函数,而可以用函数表达式定义函数
    Java8-对map过滤
    git cherry-pick 的使用
    Java8-对map排序
    Java8过滤器(Filter)
  • 原文地址:https://www.cnblogs.com/cjjsb/p/12269002.html
Copyright © 2020-2023  润新知