题目大意

维护一个 阶矩阵 ,其中最开始 ,共有 次操作,每次操作将矩阵某一行或某一列同乘一个数 ,求每一次操作后矩阵的所有元素之和。对 取模。

,且保证数据随机生成

思路

根据欧拉函数的性质,有 则考虑维护 个矩阵 的大小为 ,表示的是在其中一个因数为 时另一个要满足的因数的系数,即在上述查询中已经满足 ,下面要查 ,则一开始每个矩阵的初始元素为 。不难发现所有 的所有元素的和即为答案。

之后因为行与列思路相等,不妨先考虑行。则假设修改第 行。则查询 的每一个因数 。将 的第 行同乘 ,表示在这个因数下因为要满足另一行的所有的 均要乘 。之后发现要么全部乘一行要么乘一列,则设 表示 的第 行/列的系数,开始为 ,则 的所有元素和为

然后维护即可。

发现由于数据随机生成,则在 中随机选取一个数的期望因子数位 ,则时间复杂度为 ,空间复杂度为 的空间为

(1)在 中随机选取一个数的期望因子数位 的证明: 则单一的期望值为

代码

#include <bits/stdc++.h>
#define endl "\n"
using namespace std;
typedef long long ll;
const ll MAXN=1e5+5;
const ll MOD=1e9+7;
bool np[MAXN];
ll pm[MAXN],phi[MAXN];
vector<ll>r[MAXN],c[MAXN];
void pshuffle(){
    phi[1]=1;
    np[1]=true;
    for(int i=2;i<MAXN;++i){
        if(!np[i]){
            pm[++pm[0]]=i;
            phi[i]=i-1;
        }
        for(int j=1;j<=pm[0]&&i*pm[j]<MAXN;++j){
            ll p=pm[j];
            np[i*p]=true;
            if(i%p==0){
                phi[i*p]=phi[i]*p;
                break;
            }
            phi[i*p]=phi[i]*(p-1);
        }
    }
}
vector<ll>V[MAXN];
ll rs[MAXN],cs[MAXN];
signed main(){
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    pshuffle();
    ll n,q;
    cin>>n>>q;
    ll ans=0;
    for(int i=1;i<=n;++i){
        r[i].push_back(0);
        c[i].push_back(0);
        for(int j=1;j<=n/i;++j){
            r[i].push_back(1);
            c[i].push_back(1);
            V[i*j].push_back(i);
        }
        ans+=phi[i]*(n/i)*(n/i);

        rs[i]=cs[i]=n/i;
        ans%=MOD;
    }
    while(q--){
        char op;
        ll x,y;
        cin>>op>>x>>y;
        if(op=='R'){
            for(auto v:V[x]){
                ans=((ans-phi[v]*rs[v]%MOD*cs[v]%MOD)%MOD+MOD)%MOD;
                rs[v]+=(r[v][x/v]*(y-1)%MOD);
                rs[v]%=MOD;
                r[v][x/v]*=y;
                r[v][x/v]%=MOD;
                ans+=phi[v]*rs[v]%MOD*cs[v]%MOD;
                ans%=MOD;
            }
        }else{
            for(auto v:V[x]){
                ans=((ans-phi[v]*rs[v]%MOD*cs[v]%MOD)%MOD+MOD)%MOD;
                cs[v]+=(c[v][x/v]*(y-1)%MOD);
                cs[v]%=MOD;
                c[v][x/v]*=y;
                c[v][x/v]%=MOD;
                ans+=phi[v]*rs[v]%MOD*cs[v]%MOD;
                ans%=MOD;
            }
        }
        cout<<ans<<endl;
    }
    return 0;
}