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;
    }
    
  • 相关阅读:
    metasploit 教程之基本参数和扫描
    sql注入学习 sqlliab教程 lesson1 (sqlliab搭建教程)
    metasploit 教程之信息收集
    渗透.
    sqlmap基础入门超详细教程
    网络调试助手 全平台
    python3中的socket
    python3 udp版简单的聊天器
    提交表单外的数据方法
    centos7下端口映射
  • 原文地址:https://www.cnblogs.com/stoorz/p/13736808.html
Copyright © 2011-2022 走看看