• 数三角形


    (O(nmlogn))

    首先,我们处理本题,对于正向思维,即将所有的满足题意的三角形直接数出并不容易实现,我们可以考虑从反面入手,只要从所有的情况中减去不合法的情况即可

    对于一条横向的线,不合法的数量为 (C(m+1,3)) ,同理,对于一条竖直的线,不合法的数量即为 (C(n+1,3))

    对于一条斜向的线,我们可以从两个点之间的距离入手,考虑这两个点之间不合法情况的数量,对于横向距离为 (i) , 对于纵向距离为 (j) 三角形,一共有 ((m-i+1) imes (n-j+1)) 个,其中每个三角形对于不合法的数量的贡献为: (gcd(i,j)-1) ,同时,我们用这种方式只能处理出斜率非负的情况,再将其乘以 (2) 即可

    复杂度: (O(nmlogn))

    code

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<math.h>
    #define ll long long
    
    const ll maxn=1e3+10;
    ll n,m;
    ll vis[maxn][maxn];
    
    inline ll cal(ll x)
    {
    	if(x<3) return 0;
    	return x*(x-1)*(x-2)/6;
    }
    
    inline ll gcd(ll a,ll b)
    {
    	return b==0 ? a : gcd(b,a%b);
    }
    
    int main(void)
    {
    	scanf("%lld %lld",&n,&m);
    	
    	ll sum=cal((n+1)*(m+1));
    	
    	sum-=cal(n+1)*(m+1);
    	sum-=cal(m+1)*(n+1);
    	
    	for(int i=1;i<=n;i++)
    	{
    	 	for(int j=1;j<=m;j++)
    		{
    			sum-=(n-i+1)*(m-j+1)*(gcd(i,j)-1)*2;
    		}
    	}
    	
    	printf("%lld
    ",sum);
    	
    	return 0;
    }
    

    (O(n))

    我们可以考虑对于斜着的线的计数方案,即:

    [displaystyle sum_{i=1}^{n}{displaystyle sum_{j=1}^{m}{(n-i+1)(m-j+1)(gcd(i,j)-1)}} ]

    那么,我们可以用 (id) 函数改写为:

    [displaystyle sum_{i=1}^{n}{displaystyle sum_{j=1}^{m}{(n-i+1)(m-j+1)[id(gcd(i,j)-1)]}} ]

    卷开即得:

    [displaystyle sum_{i=1}^{n}{displaystyle sum_{j=1}^{m}{(n-i+1)(m-j+1) displaystyle sum_{d|gcd(i,j)}^{d eq 1}{varphi(d)}}} ]

    变更枚举顺序得:

    [displaystyle sum_{d=2}^{min(n,m)}{varphi(d) displaystyle sum_{i=1}^{lfloor{frac{n}{d}} floor}{(n-i imes d +1 )} displaystyle sum_{j=1}^{lfloor{frac{m}{d}} floor}{(m-j imes d +1 )}} ]

    对于式 (displaystyle sum_{i=1}^{lfloor{frac{n}{d}} floor}{(n-i imes d +1 )}) ,显然即为一个等差数列求和,其首项为 (n-1 imes d+1) ,末项为 (n- lfloor{frac{n}{d}} floor imes d +1) ,则和为

    [((n-1 imes d+1)+(n- lfloor{frac{n}{d}} floor imes d +1)) imes lfloor{frac{n}{d}} floor imes frac{1}{2} ]

    即为:

    [{(n-d+(n mod d)+2)} imes lfloor{frac{n}{d}} floor imes frac{1}{2} ]

    故总和为:

    [frac{1}{4} displaystyle sum_{d=2}^{min(n,m)}{varphi(d)}{{(n-d+(n mod d)+2)} imes lfloor{frac{n}{d}} floor}{{(m-d+(m mod d)+2)} imes lfloor{frac{m}{d}} floor} ]

    则线性筛预处理欧拉函数后 (O(n)) 求和即可

    code

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<math.h>
    #include<algorithm>
    #define ll long long
    
    const ll maxn=1e3+10;
    ll n,m,tot,sum,ans;
    ll phi[maxn],vis[maxn],prime[maxn];
    
    inline ll cal(ll x)
    {
    	if(x<3) return 0;
    	return x*(x-1)*(x-2)/6;
    }
    
    inline void pre(ll x)
    {
    	phi[1]=1;
    	
    	for(int i=2;i<=x;i++)
    	{
    		if(!vis[i])
    		{
    			vis[i]=1;
    			prime[++tot]=i;
    			phi[i]=i-1;
    		}
    		
    		for(int j=1;j<=tot&&i*prime[j]<=x;j++)
    		{
    			vis[i*prime[j]]=1;
    			
    			if(i%prime[j]==0)
    			{
    				phi[i*prime[j]]=phi[i]*prime[j];
    				break;
    			}
    			
    			phi[i*prime[j]]=phi[i]*(prime[j]-1);
    		}
    	}
    }
    
    int main(void)
    {
    	scanf("%lld %lld",&n,&m);
    	
    	pre(maxn-5);
    	
    	ans=cal((n+1)*(m+1));
    	ans-=cal(n+1)*(m+1);
    	ans-=cal(m+1)*(n+1); 	
    	
    //	for(int i=1;i<=100;i++)
    //	{
    //		printf("%lld
    ",phi[i]);
    //	}
    	
    	for(int i=2;i<=std::min(n,m);i++)
    	{
    		sum+=phi[i]*(n-i+(n%i)+2)*(n/i)*(m-i+(m%i)+2)*(m/i)/2;
    	}
    	
    //	printf("%lld
    ",sum);
    	
    	printf("%lld
    ",ans-sum);
    }
    
  • 相关阅读:
    了解 Spring Data JPA
    Spring MVC 方法注解拦截器
    Spring MVC拦截器+注解方式实现防止表单重复提交
    java中return语句的用法总结
    equal方法在String类与Object类中的区别
    instanceof用法
    EL 简介及用法
    JAVA 四大域对象总结
    JSP基本语法
    Servlet请求转发 RequestDispatcher接口知识点
  • 原文地址:https://www.cnblogs.com/jd1412/p/14277918.html
Copyright © 2020-2023  润新知