hdu 4483 Lattice triangle 数论之组合数

来源:互联网 发布:药智数据cfda39健康网 编辑:程序博客网 时间:2024/06/05 14:15
#include <stdio.h>#include <iostream>using namespace std;#define maxn 100001#define LL long longconst LL mod=1000000007;//最好用常量,我用宏定义,*6的时候爆了,怎么也找不出来LL x[maxn],y[maxn],z[maxn],phi[maxn],n;void init(){    LL i,j,k;    //欧拉函数,phi[i]表示不超过i的与i互质的整数个数    for(i=2;i<maxn;i++)phi[i]=0;    phi[1]=1;    for(i=2;i<maxn;i++)        if(!phi[i])        for(j=i;j<=maxn;j+=i){            if(!phi[j])phi[j]=j;            phi[j]=phi[j]/i*(i-1);        }    x[1]=z[1]=1;    y[1]=2;    for(i=2;i<maxn;i++)    {        x[i]=(x[i-1]+phi[i]*2)%mod;        y[i]=(y[i-1]+phi[i]*i*3)%mod;        z[i]=(z[i-1]+phi[i]*i%mod*i)%mod;    }}int main(){    LL T;    init();    cin>>T;    while(T--)    {        LL k,t,ans,m;        cin>>n;        n++;        t=(n*n)%mod;        LL md=mod*6;        ans=t*(t-1)%md*(t-2)%md/6;//除法取余;        ans-=t*(n-1)%md*(n-2)*2%md/6;        t=0;        for(k=2;k<n;k++)        {            m=(n-1)/k;            t=(t+(k-1)*(x[m]*n%mod*n%mod-n*k%mod*y[m]%mod+k*k%mod*z[m]%mod))%mod;        }        ans-=t*2;        cout<<(ans%mod+mod)%mod<<endl;    }    return 0;}/*题意:在n*n的网格内找到3个格点,使它能构成三角形,问能构成多少个三角形?方法:    总共有t=(n+1)*(n+1)个格点,所以令n++    1.任取三个点ans=c(t,3)    2.去掉在一条直线三的三个点ans=ans-c(n,3)*n*2    3.还要去掉在一条斜线上的三个点:        对于长宽为i,j的矩形,对角线上有gcd(i,j)-1个格点(不包括两端点),这样我们就能枚举矩形,去掉不能构成三角形的三个点        则要去掉的方案数为∑∑(n-i)*(n-j)*(gcd(i,j)-1);        本题n太大,还要优化成O(n)复杂度才可以    优化:        令i=a*k,j=b*k,其中k为(i,j)的最大公约数        则条件3的方案数为sum=∑∑∑(n-a*k)*(n-b*k)*(k-1)=∑∑∑(n*n-(a+b)*n*k+a*b*k*k)*(k-1)            =∑[k](k-1)*(n*n*∑∑1+n*k*∑∑(a*b)+k*k*∑∑(a*b))                其中i,j<n,所以a,b<=(n-1)/k=m;        phi[i]为欧拉函数,a,b<=m中,∑∑=a,b两两互质的个数=1+(phi[2]+phi[3]+...+phi[m])*2        phi[i]的个数只是说a<b,b=i时有多少个,还有a>b,所以要乘以2,除了a=b=1以外                定理:如果gcd(a,b)==1,则gcd(a,a-b)==1。所以phi[i]个与i互质的数种,成对出现,每对之和为i        所以∑∑(a+b)=∑(phi[i]/2*i+phi[i])*2                由上述定理可以知道:phi[i]个互质的数与i的乘积之和为i*(x1+x2+..xm)=i*ph[i]/2*i;        所以∑∑(a*b)=∑(phi[i]*i*i/2)*2*/

原创粉丝点击