列表

详情


NC19948. [CQOI2017]小Q的表格

描述

小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,都要 满足b×f(a,a+b)=(a+b)*f(a,b)。
为了完成任务,一开始表格里面的数很有规律,第a行第b列的数恰好等于a*b, 显然一开始是满足上述两个条件的。为了完成任务,小Q需要不断的修改表格里面的数,每当修改了一个格子的数之后,为了让表格继续满足上述两个条件,小Q还需要把这次修改能够波及到的全部格子里都改为恰当的数。由于某种神奇的力量驱使,已经确保了每一轮修改之后所有格子里的数仍然都是整数。为了完成任务,小Q还需要随时 获取前k行前k列这个有限区域内所有数的和是多少,答案可能比较大,只需要算出答案mod1,000,000,007之后的结 果。

输入描述

第1行包含两个整数m,n,表示共有m次操作,所有操作和查询涉及到的行编号和列编号都不超过n。
接下来m行,每行4个整数a,b,x,k表示把第a行b列的数改成x,然后把它能够波及到的所有格子全部修改,保证修改之后所有格子的数仍然都是整数,修改完成后计算前k行前k列里所有数的和。
1 ≤ m ≤ 10000,1 ≤ a,b,k ≤ N ≤ 4*10^6,0 ≤ x ≤ 10^18

输出描述

输出共m行,每次操作之后输出1行,表示答案mod 1,000,000,007之后的结果。

示例1

输入:

3 3
1 1 1 2
2 2 4 3
1 2 4 2

输出:

9
36
14

说明:

一开始,表格的前3行前3列如图中左边所示,前2次操
作后表格没有变化,第3次操作之后的表格如右边所示。
1 2 3 2 4 6
2 4 6 4 4 12
3 6 9 6 12 9

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++14(g++5.4) 解法, 执行用时: 863ms, 内存消耗: 83800K, 提交时间: 2019-06-24 17:07:56

#include <bits/stdc++.h>
#define fi first
#define se second
#define pii pair<int,int>
#define mp make_pair
#define pb push_back
#define space putchar(' ')
#define enter putchar('\n')
#define eps 1e-10
#define ba 47
#define MAXN 4000005
//#define ivorysi
using namespace std;
typedef long long int64;
typedef unsigned int u32;
typedef double db;
template<class T>
void read(T &res) {
    res = 0;T f = 1;char c = getchar();
    while(c < '0' || c > '9') {
	if(c == '-') f = -1;
	c = getchar();
    }
    while(c >= '0' && c <= '9') {
	res = res * 10 +c - '0';
	c = getchar();
    }
    res *= f;
}
template<class T>
void out(T x) {
    if(x < 0) {x = -x;putchar('-');}
    if(x >= 10) {
	out(x / 10);
    }
    putchar('0' + x % 10);
}
const int MOD = 1000000007;
int M,N;
int f[MAXN],prime[MAXN],tot,phi[MAXN];
int h[MAXN],bl[2005],br[2005],id[MAXN],cnt,lz[2005];
int sum[MAXN];
bool nonprime[MAXN];
int inc(int a,int b) {
    return a + b >= MOD ? a + b - MOD : a + b;
}
int mul(int a,int b) {
    return 1LL * a * b % MOD;
}
void update(int &x,int y) {
    x = inc(x,y);
}
int gcd(int a,int b) {
    return b == 0 ? a : gcd(b,a % b);
}
int main(){
#ifdef ivorysi
    freopen("f1.in","r",stdin);
#endif
    read(M);read(N);
    phi[1] = 1;
    h[1] = 1;
    for(int i = 2 ; i <= N ; ++i) {
	if(!nonprime[i]) {
	    prime[++tot] = i;
	    phi[i] = i - 1;
	}
	for(int j = 1 ; j <= tot ; ++j) {
	    if(prime[j] > N / i) break;
	    nonprime[i * prime[j]] = 1;
	    if(i % prime[j] == 0) {
		phi[i * prime[j]] = phi[i] * prime[j];
		break;
	    }
	    else {
		phi[i * prime[j]] = phi[i] * phi[prime[j]];
	    }
	}
	h[i] = mul(phi[i],mul(i,i));
	update(h[i],h[i - 1]);
    }
    for(int i = 1 ; i <= N ; ++i) {
	sum[i] = mul(i,i);
	f[i] = mul(i,i);
	update(sum[i],sum[i - 1]);
    }
    int S = sqrt(N);
    for(int i = 1 ; i <= N ; ++i) {
	int r = min(N,i + S - 1);
	++cnt;
	bl[cnt] = i;br[cnt] = r;i = r;
	for(int j = bl[cnt] ; j <= br[cnt] ; ++j) id[j] = cnt;
    }
    int a,b,k;
    int64 x;
    for(int i = 1 ; i <= M ; ++i) {
	read(a);read(b);read(x);read(k);
    int g = gcd(a,b);
	int d = (x / (1LL * a / g * b / g)) % MOD;
	int c = inc(d,MOD - f[g]);
	f[g] = d;
	for(int j = g ; j <= br[id[g]] ; ++j) {
	    update(sum[j],c);
	    
	}
	for(int j = id[g] + 1 ; j <= cnt ; ++j) update(lz[j],c);
	int res = 0;
	for(int j = 1 ; j <= k ; ++j) {
	    int r = k / (k / j);
	    int s = inc(sum[r],lz[id[r]]);
	    s = inc(s,MOD - inc(sum[j - 1],lz[id[j - 1]]));
	    update(res,mul(s,h[k / j]));
	    j = r;
	}
	out(res);enter;
    }
    return 0;
}

C++11(clang++ 3.9) 解法, 执行用时: 1429ms, 内存消耗: 64160K, 提交时间: 2020-08-25 20:49:08

#include<cstdio>
#define N 4000005
#define mod 1000000007
using namespace std;
int c[N],n,p[N],v[N],phi[N],f[N];
void inc(int i,int x){for(;i<=n;i+=-i&i)c[i]=(c[i]+x)%mod;}
int query(int i){
	int ans=0;
	for(;i;i-=-i&i)ans=(ans+c[i])%mod;
	return ans;
}
int gcd(int a,int b){
	int r=a%b;
	while(r)a=b,b=r,r=a%b;
	return b;
}
int qp(int a,int x){
	int i=1;
	for(;x;x/=2,a=1ll*a*a%mod)if(x&1)i=1ll*i*a%mod;
	return i;
}
int main(){
	int m,i,j,w,k;long long x;
	//freopen("input.in","r",stdin);
	scanf("%d%d",&m,&n);
	for(i=v[phi[1]=1]=2;i<=n;i++){
		if(!v[i])phi[v[i]=p[++p[0]]=i]=i-1;
		for(j=1;j<=p[0]&&i*p[j]<=n;j++){
			v[i*p[j]]=1;
			if(i%p[j])phi[i*p[j]]=phi[i]*(p[j]-1);
			else{
				phi[i*p[j]]=phi[i]*p[j];
				break;
			}
		}
	}
	for(i=1;i<=n;i++){
		phi[i]=(1ll*i*i%mod*phi[i]%mod+phi[i-1])%mod;
		inc(i,f[i]=1ll*i*i%mod);
	}
	while(m--){
		scanf("%d%d%lld%d",&i,&j,&x,&k);
		w=gcd(i,j);
		x=1ll*w*w%mod*(x%mod)%mod*qp(1ll*i*j%mod,mod-2)%mod;
		inc(w,(x-f[w]+mod)%mod);f[w]=x;
		for(i=1,w=0;i<=k;i=j+1){
			j=k/(k/i);
			w=(w+1ll*phi[k/i]*(query(j)-query(i-1))%mod)%mod;
		}
		printf("%d\n",(w+mod)%mod);
	}
	return 0;
}

上一题