zoukankan      html  css  js  c++  java
  • 【洛谷P1829】Crash的数字表格 / JZPTAB

    题目

    题目链接:https://www.luogu.com.cn/problem/P1829
    今天的数学课上,Crash 小朋友学习了最小公倍数(Least Common Multiple)。对于两个正整数 \(a\)\(b\)\(\text{lcm}(a,b)\) 表示能同时整除 \(a\)\(b\) 的最小正整数。例如,\(\text{lcm}(6, 8) = 24\)

    回到家后,Crash 还在想着课上学的东西,为了研究最小公倍数,他画了一张 $ n \times m$ 的表格。每个格子里写了一个数字,其中第 \(i\) 行第 \(j\) 列的那个格子里写着数为 \(\text{lcm}(i, j)\)

    看着这个表格,Crash 想到了很多可以思考的问题。不过他最想解决的问题却是一个十分简单的问题:这个表格中所有数的和是多少。当 \(n\)\(m\) 很大时,Crash 就束手无策了,因此他找到了聪明的你用程序帮他解决这个问题。由于最终结果可能会很大,Crash 只想知道表格里所有数的和 \(\bmod 20101009\) 的值。

    思路

    90pts

    自己瞎推了一个 sb 式子,以为 \(O(n\log n)\) 可以卡过,结果 T 飞了 /kk。

    \[ans=\sum^{n}_{i=1}\sum^{m}_{j=1}\frac{ij}{\gcd(i,j)} \]

    \[=\sum^{\min(n,m)}_{i=1}\frac{\sum^{\min(n,m)}_{i|d}\mu(\frac{d}{i})\times (d+\lfloor\frac{n}{d}\rfloor\times d)\times (d+\lfloor\frac{m}{d}\rfloor\times d)}{i} \]

    直接暴力乱搞即可。时间复杂度 \(O(n\log n)\)Link

    100pts

    显然有

    \[ans=\sum^{n}_{d=1}\times \sum^{\lfloor\frac{n}{d}\rfloor}_{i=1}\sum^{\lfloor\frac{m}{d}\rfloor}_{n=1}ij[\gcd(i,j)==1] \]

    \(f(n,m)=\sum^{n}_{i=1}\sum^{m}_{n=1}ij[\gcd(i,j)==1]\),那么

    \[f(n,m)=\sum^{\min(n,m)}_{d=1}\frac{(d+\lfloor\frac{n}{d}\rfloor\times d)\times \lfloor\frac{n}{d}\rfloor}{2}\times \frac{(d+\lfloor\frac{m}{d}\rfloor\times d)\times \lfloor\frac{m}{d}\rfloor}{2}\times \mu(d) \]

    \[=\frac{\sum^{\min(n,m)}_{d=1}d^2\mu(d)(\lfloor\frac{n}{d}\rfloor+1)(\lfloor\frac{m}{d}\rfloor+1)\lfloor\frac{n}{d}\rfloor\lfloor\frac{m}{d}\rfloor}{4} \]

    预处理 \(sum[i]=sum[i-1]+\mu(i)+i^2\),然后整除分块搞即可。
    带回原式,\(ans=\sum^{\min(n,m)}_{d=1}d\times f(\lfloor\frac{n}{d}\rfloor,\lfloor\frac{m}{d}\rfloor)\),依然可以整除分块。
    时间复杂度 \(O(n)\)

    代码

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    
    const ll N=10000010,MOD=20101009;
    ll n,m,cnt,mu[N],prm[N],sum[N];
    ll ans,pows[N];
    bool v[N];
    
    void findprm(ll n)
    {
    	mu[1]=1;
    	for (ll i=2;i<=n;i++)
    	{
    		if (!v[i]) prm[++cnt]=i,mu[i]=-1;
    		for (ll j=1;j<=cnt;j++)
    		{
    			if (prm[j]>n/i) break;
    			v[prm[j]*i]=1; mu[prm[j]*i]=-mu[i];
    			if (!(i%prm[j]))
    			{
    				mu[prm[j]*i]=0;
    				break;
    			}
    		}
    	}
    }
    
    ll fpow(ll x,ll k)
    {
    	ll ans=1;
    	for (;k;k>>=1,x=x*x%MOD)
    		if (k&1) ans=ans*x%MOD;
    	return ans;
    }
    
    ll solve(ll n,ll m)
    {
    	ll ans=0;
    	for (ll l=1,r;l<=min(n,m);l=r+1)
    	{
    		r=min(n/(n/l),m/(m/l));
    		ans=(ans+(sum[r]-sum[l-1])*(n/l+1)%MOD*(m/l+1)%MOD*(n/l)%MOD*(m/l))%MOD;
    	}
    	return ans;
    }
    
    int main()
    {
    //	freopen("data.in","r",stdin);
    	findprm(N-1);
    	for (ll i=1;i<N;i++)
    		sum[i]=(sum[i-1]+mu[i]*1LL*i*i)%MOD; 
    	scanf("%lld%lld",&n,&m);
    	for (ll l=1,r;l<=min(n,m);l=r+1)
    	{
    		r=min(n/(n/l),m/(m/l));
    		ans=(ans+1LL*(l+r)*(r-l+1)/2LL%MOD*solve(n/l,m/l))%MOD;
    	}
    	printf("%lld",(ans%MOD+MOD)%MOD*fpow(4,MOD-2)%MOD);
    	return 0;
    }
    
  • 相关阅读:
    Shadow SSDT详解、WinDbg查看Shadow SSDT
    两种方法获取shadow ssdt
    r0遍历系统进程方法总结
    枚举PEB获取进程模块列表
    用户层获取TEB PEB结构地址 遍历进程模块.doc
    Process32First 返回FALSE的原因
    windows内核需要注意的
    hive中遇到的问题
    解读:计数器Counter
    hadoop System times on machines may be out of sync. Check system time and time zones.
  • 原文地址:https://www.cnblogs.com/stoorz/p/13765352.html
Copyright © 2011-2022 走看看