zoukankan      html  css  js  c++  java
  • 【洛谷P3312】数表

    题目

    题目链接:https://www.luogu.com.cn/problem/P3312
    有一张 \(n\times m\) 的数表,其第 \(i\) 行第 \(j\) 列(\(1\le i\le n\)\(1\le j\le m\))的数值为能同时整除 \(i\)\(j\) 的所有自然数之和。给定 \(a\),计算数表中不大于 \(a\) 的数之和。

    思路

    先不考虑 \(a\) 的限制,那么 \((i,j)\) 的数值即为 \(\gcd(i,j)\) 的因子之和(设为 \(g(i)\))。\(g(i)\) 可以 \(O(n\log n)\) 预处理出。

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

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

    当有 \(a\) 的限制时,只有 \(g(x)\leq a\)\(g(x)\) 才可以产生贡献。所以我们将询问按 \(a\) 排序,数字 \(x\)\(g(x)\) 排序,对于一个询问 \(a\)\(g(x)\leq a\) 的所有 \(g(x)\)\(x\) 倍数的贡献加上,然后再询问一段区间的和。
    用树状数组处理即可。然后就是整除分块乱搞了。
    时间复杂度 \(O(Q\sqrt{n}+Q\log^2 n)\)

    代码

    #include <bits/stdc++.h>
    using namespace std;
    typedef unsigned int uint;
    
    const int N=100010;
    int Q,tot,prm[N],mu[N],g[N];
    uint ans[N];
    bool v[N];
    
    struct Query
    {
    	int n,m,a,id;
    }ask[N];
    
    struct node
    {
    	int g,id;
    }a[N];
    
    bool cmp1(Query x,Query y)
    {
    	return x.a<y.a;
    }
    
    bool cmp2(node x,node y)
    {
    	return x.g<y.g;
    }
    
    void findprm(int n)
    {
    	mu[1]=1;
    	for (int i=2;i<=n;i++)
    	{
    		if (!v[i])
    			prm[++tot]=i,mu[i]=-1;
    		for (int j=1;j<=tot;j++)
    		{
    			if (i>n/prm[j]) break;
    			v[prm[j]*i]=1; mu[prm[j]*i]=-mu[i];
    			if (!(i%prm[j]))
    			{
    				mu[i*prm[j]]=0;
    				break;
    			}
    		}
    	}
    }
    
    struct BIT
    {
    	uint c[N];
    	
    	void add(int x,uint v)
    	{
    		for (int i=x;i<N;i+=i&-i)
    			c[i]+=v;
    	}
    	
    	uint query(int x)
    	{
    		uint ans=0;
    		for (int i=x;i;i-=i&-i)
    			ans+=c[i];
    		return ans;
    	}
    }bit;
    
    int main()
    {
    	findprm(N-10);
    	for (int i=1;i<=N-10;i++)
    		for (int j=i;j<=N-10;j+=i)
    			g[j]+=i;
    	for (int i=1;i<=N-10;i++)
    		a[i]=(node){g[i],i};
    	sort(a+1,a+1+N-10,cmp2);
    	scanf("%d",&Q);
    	for (int i=1;i<=Q;i++)
    	{
    		scanf("%d%d%d",&ask[i].n,&ask[i].m,&ask[i].a);
    		ask[i].id=i;
    	}
    	sort(ask+1,ask+1+Q,cmp1);
    	for (int i=1,j=1;i<=Q;i++)
    	{
    		for (;j<=N-10 && a[j].g<=ask[i].a;j++)
    			for (int k=a[j].id;k<=N-10;k+=a[j].id)
    				bit.add(k,1U*mu[k/a[j].id]*a[j].g);
    		int n=ask[i].n,m=ask[i].m;
    		for (int l=1,r;l<=min(n,m);l=r+1)
    		{
    			r=min(n/(n/l),m/(m/l));
    			ans[ask[i].id]+=1U*(n/l)*(m/l)*(bit.query(r)-bit.query(l-1));
    		}
    	}
    	for (int i=1;i<=Q;i++)
    		printf("%d\n",(int)(2147483647U&ans[i]));
    	return 0;
    }
    
  • 相关阅读:
    git 操作
    vim使用指北 ---- Multiple Windows in Vim
    Unity 异步网络方案 IOCP Socket + ThreadSafe Queue
    unity 四元数, 两行等价的代码
    golang的项目结构 相关知识
    stencil in unity3d
    一段tcl代码
    16_游戏编程模式ServiceLocator 服务定位
    15_游戏编程模式EventQueue
    14_ Component 游戏开发组件模式
  • 原文地址:https://www.cnblogs.com/stoorz/p/13736808.html
Copyright © 2011-2022 走看看