日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 综合教程 >内容正文

综合教程

数三角形

發(fā)布時間:2024/8/26 综合教程 25 生活家
生活随笔 收集整理的這篇文章主要介紹了 数三角形 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

link

(O(nmlogn))

首先,我們處理本題,對于正向思維,即將所有的滿足題意的三角形直接數(shù)出并不容易實現(xiàn),我們可以考慮從反面入手,只要從所有的情況中減去不合法的情況即可

對于一條橫向的線,不合法的數(shù)量為 (C(m+1,3)) ,同理,對于一條豎直的線,不合法的數(shù)量即為 (C(n+1,3)) 個

對于一條斜向的線,我們可以從兩個點之間的距離入手,考慮這兩個點之間不合法情況的數(shù)量,對于橫向距離為 (i) , 對于縱向距離為 (j) 三角形,一共有 ((m-i+1) imes (n-j+1)) 個,其中每個三角形對于不合法的數(shù)量的貢獻為: (gcd(i,j)-1) ,同時,我們用這種方式只能處理出斜率非負的情況,再將其乘以 (2) 即可

復(fù)雜度: (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))

我們可以考慮對于斜著的線的計數(shù)方案,即:

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

那么,我們可以用 (id) 函數(shù)改寫為:

[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}ozvdkddzhkzd}floor}{(n-i imes d +1 )} displaystyle sum_{j=1}^{lfloor{frac{m}ozvdkddzhkzd}floor}{(m-j imes d +1 )}}
]

對于式 (displaystyle sum_{i=1}^{lfloor{frac{n}ozvdkddzhkzd}floor}{(n-i imes d +1 )}) ,顯然即為一個等差數(shù)列求和,其首項為 (n-1 imes d+1) ,末項為 (n- lfloor{frac{n}ozvdkddzhkzd}floor imes d +1) ,則和為

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

即為:

[{(n-d+(n mod d)+2)} imes lfloor{frac{n}ozvdkddzhkzd}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}ozvdkddzhkzd}floor}{{(m-d+(m mod d)+2)} imes lfloor{frac{m}ozvdkddzhkzd}floor}
]

則線性篩預(yù)處理歐拉函數(shù)后 (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);
}

總結(jié)

以上是生活随笔為你收集整理的数三角形的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。