zoukankan      html  css  js  c++  java
  • [BZOJ3518] 点组计数

    题面

    显然

    横着或竖着共有(n*(_3^m)+m*(_3^n))

    斜着的方案数为

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

    就是枚举两个端点

    令其中一个为原点

    另一个为((i,j))

    (gcd(i,j)=d)

    所以最靠近原点的整点是((frac{i}{d},frac{j}{d}))

    所以从这个点到((i,j))(frac{i}{(frac{i}{d})}=d)个整点

    除去((i,j))本身

    那么他们之间有(gcd(i,j)-1)个整点

    然后可以上下左右平移这个线段

    答案就是((gcd(i,j)-1)(n-i)(m-j))

    考虑如何计算这个式子

    (-1)提出来再反演即可

    [sum_{i=1}^{n}sum_{j=1}^{m}{gcd(i,j)(n-i)(m-j)} \=sum_{i=1}^{n}sum_{j=1}^{m}{sum_{d|gcd(i,j)}{varphi(d)}(n-i)(m-j)} \=sum_{d=1}^{n}varphi(d)sum_{i=1}^{lfloor frac{n}{d} floor}{(n-i*d)}sum_{j=1}^{lfloor frac{m}{d} floor}{(m-j*d)} \=sum_{d=1}^{n}varphi(d)*(n*lfloor frac{n}{d} floor-d*frac{lfloor frac{n}{d} floor*(lfloor frac{n}{d} floor-1)}{2})*(m*lfloor frac{m}{d} floor-d*frac{lfloor frac{m}{d} floor*(lfloor frac{m}{d} floor-1)}{2}) ]

    因为提了一个$-1 $

    答案先减去(frac{(n-1)*n}{2}+frac{(m-1)*m}{2})

    因为端点顺序不固定

    答案乘(2)

    最后再加上(n*(_3^m)+m*(_3^n))即可

    #include "bits/stdc++.h"
    
    using namespace std;
    
    #define ll long long
    
    const int p=1e9+7;
    const int N=1e6+7;
    
    int tot;
    int pri[N],phi[N];
    
    inline void init(int n){
    	phi[1]=1;
    	for(int i=2;i<=n;++i){
    		if(!phi[i])pri[++tot]=i,phi[i]=i-1;
    		for(int j=1,tmp;j<=tot&&(tmp=i*pri[j])<=n;++j){
    			if(i%pri[j]==0){
    				phi[tmp]=phi[i]*pri[j];
    				break;
    			}
    			phi[tmp]=phi[i]*phi[pri[j]];
    		}
    	}
    }
    
    inline ll s(ll x){
    	return (x*(x+1)>>1)%p;
    }
    
    inline ll calc(ll n,ll d){
    	return ((n/d*n-d*s(n/d))%p+p)%p;
    }
    
    inline ll C3(ll x){
    	return (x<3?0:x*(x-1)*(x-2)/6)%p;
    }
    
    int main(){
    	int n,m;
    	scanf("%d %d",&n,&m);
    	if(n>m)swap(n,m);
    	ll ans=0;
    	init(n);
    	for(int d=1;d<=n;++d){
    		(ans+=phi[d]*calc(n,d)%p*calc(m,d))%=p;;
    	}
    	(ans+=p-s(n-1)*s(m-1)%p)%p;
    	printf("%lld
    ",(ans*2%p+m*C3(n)%p+n*C3(m)%p)%p);
    	return 0;
    }
    
    
  • 相关阅读:
    PHP 使用 GET 传递数组变量
    Java实现 蓝桥杯 算法训练 数据交换
    Java实现 蓝桥杯 算法训练 数据交换
    Java实现 蓝桥杯 算法训练 数据交换
    Java实现 蓝桥杯 算法训练 景点游览
    Java实现 蓝桥杯 算法训练 景点游览
    Java实现 蓝桥杯 算法训练 景点游览
    Java实现 蓝桥杯 算法训练 二进制数数
    Java实现 蓝桥杯 算法训练 二进制数数
    Java实现 蓝桥杯 算法训练 二进制数数
  • 原文地址:https://www.cnblogs.com/yicongli/p/10165502.html
Copyright © 2011-2022 走看看