G - Pyramid ( 打表找规律 + 逆元 )
题意:
求n行三角形中等边三角形个数,图二的三角形也算。 n<=1e9
思路:
打表找下规律,打表方法:把所有点扔坐标系里n^3爆搜即可
打出来为 1,5,15,35,70,126,210...
没感觉,作差 4, 10, 20, 35, 56, 84
还是没感觉,作差 6, 10, 15, 21, 28
发现此时的差递增1?也就是再作差4, 5, 6, 7是等差数列
也就是再作差1, 1, 1为常数
相当于函数 An 求四次导为常数!( 如果他是个连续函数的话 )
于是我们设 An = a∗ + b∗
+ c∗
+ d∗n + e (别忘记常数)
解出a, b, c, d, e,
记得保留分数形式,得出a=1/24 , b=6/24, c=11/24, d=6/24, e=0.
这样提出一个1/24来,An = (1/24)*( + 6*
+ 11∗
+ 6∗n )
然后逆元+O(1)代公式就完事了
打表时注意两个两个double类型数的相等判断需要用 fabs(a-b)<0.00001
打表代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod = 1e9+7;
struct node {
double x,y;
}a[10001];
int n,cnt;
double dis( int i, int j )
{
return sqrt( (a[i].x-a[j].x)*(a[i].x-a[j].x) + (a[i].y-a[j].y)*(a[i].y-a[j].y) );
}
int judge( int i, int j, int k )
{
double a = dis(i,j);
double b = dis(i,k);
double c = dis(j,k);
if ( fabs(a-b)<=0.001 && fabs(b-c)<=0.001 && fabs(a-c)<=0.001 ) return 1;
return 0;
}
int main()
{
while (cin >> n) {
cnt = 0;
double posy = 0;
double posx = 0;
for ( int i=n; i>=0; i-- ) {
for ( int j=0; j<=i; j++ ) {
a[cnt].x = posx;
a[cnt++].y = posy + 2*j;
}
posx += sqrt(3);
posy += 1.0;
}
//for ( int i=0; i<cnt; i++ ) cout << a[i].x<<" "<<a[i].y<<endl;
int ans = 0;
for ( int i=0; i<cnt; i++ ) {
for ( int j=i+1; j<cnt; j++ ) {
for ( int k=j+1; k<cnt; k++ ) {
if ( judge(i,j,k)==1 ) {
ans ++;
}
}
}
}
cout << ans << endl;
}
return 0;
}
ac代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod = 1e9+7;
int main()
{
ll inv24 = (mod+1)/24;
ll n,x;
cin >> n;
while ( n-- ) {
scanf("%lld",&x);
ll ans = (((((x*x)%mod)*x)%mod)*x)%mod + 6*(((x*x)%mod)*x)%mod
+(11*(x*x%mod)%mod) + 6*x%mod; // 注意11*x*x可能会long long, 需要先对x*x取模再乘11
ans %= mod;
ans = ans*inv24%mod;
printf("%lld\n",ans);
}
return 0;
}