Description
Chocola is addicted to a phone game named white grid. There’s a cross with 5 empty grids on the game interface.
Chocola can write 5 different numbers ranging between 1 and n (inclusive) into grids.
When the sum of 3 horizontal grids is equal to the sum of 3 vertical grids, Chocola can earn some score.
Then grids will be clear and Chocola can start the game again.
But the game system doesn’t allow Chocola to earn score by the same cross.
Vanilla also play this game and she can play the game again and again.
Chocola can’t understand why Vanilla is so skillful?
How many times has Vanilla played?!
Now Chocola wonders how many ways can she earn score.
±–+
| |
±–±--±–+
| | | |
±–±--±–+
| |
±–+
输入格式
The input file begins with an integer T (T <= 10) in one row indicating the number of test case.
Then T lines follow, one test case per line. Each line consists of an positive integer n (1 <= n <= 100)
输出格式
For each test case, print one line containing the answer.
输入样例
2
5
6
输出样例
24
112
题意:求题给方格中横纵填不同数使得横纵和相等的填法 |
思路(规律):
标签“暴力”害人不浅啊。。。dfs了几次都TL了。静下心来观察了一下规律,其实O(n)就可以过了。
1.五个格子,n<=4肯定没有解,输出0。
2.n>=5时,宏观的规律就是中间的先不管(公共嘛),找到四个数满足横纵和相等,然后四个数横方向可以两两交换,纵方向可以两两交换,横纵同时还可以交换,所以拿到一个四元组其结果就是ans += 2x2x2x(n-4)。为什么要多乘上一个(n-4)?这就是中间那个。你拿了四个数,你的n又比4大,所以随便找一个剩下来的数放中间就行了。
3.现在看这个四元组怎么选。这个时候就枚举加和结果的目标数就行了。最后不是sum = a+b = c+d吗,我们就枚举这个sum,然后就是一个小学知识——把一个数拆分成两个数的和,然后选出两组来当ab和cd即可。
就比如样例的5得出24是这么来的:
4.那么目前规律就很显而易见了。我们先预处理一下1->200之间的可能被当做加和结果的数,这些数能拆分成 i/2个(若是偶数要舍去一个含相同项的)。然后每次case拿到一个n就从5到200之间枚举目标数即可。时间复杂度O(n)。
AC代码:
#include<iostream>
#include<string>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<map>
#include <queue>
#include<sstream>
#include <stack>
#include <set>
#include <bitset>
#include<vector>
#define FAST ios::sync_with_stdio(false)
#define abs(a) ((a)>=0?(a):-(a))
#define sz(x) ((int)(x).size())
#define all(x) (x).begin(),(x).end()
#define mem(a,b) memset(a,b,sizeof(a))
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define rep(i,a,n) for(int i=a;i<=n;++i)
#define per(i,n,a) for(int i=n;i>=a;--i)
#define pb push_back
#define mp make_pair
#define fi first
#define se second
using namespace std;
typedef long long ll;
typedef pair<ll,ll> PII;
const int maxn = 3e4+2;
const int inf=0x3f3f3f3f;
const double eps = 1e-7;
const double pi=acos(-1.0);
const int mod = 1e9+7;
inline int lowbit(int x){return x&(-x);}
ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
void ex_gcd(ll a,ll b,ll &d,ll &x,ll &y){if(!b){d=a,x=1,y=0;}else{ex_gcd(b,a%b,d,y,x);y-=x*(a/b);}}//x=(x%(b/d)+(b/d))%(b/d);
inline ll qpow(ll a,ll b,ll MOD=mod){ll res=1;a%=MOD;while(b>0){if(b&1)res=res*a%MOD;a=a*a%MOD;b>>=1;}return res;}
inline ll inv(ll x,ll p){return qpow(x,p-2,p);}
inline ll Jos(ll n,ll k,ll s=1){ll res=0;rep(i,1,n+1) res=(res+k)%i;return (res+s)%n;}
inline ll read(){ ll f = 1; ll x = 0;char ch = getchar();while(ch>'9'||ch<'0') {if(ch=='-') f=-1; ch = getchar();}while(ch>='0'&&ch<='9') x = (x<<3) + (x<<1) + ch - '0', ch = getchar();return x*f; }
int dir[4][2] = { {1,0}, {-1,0},{0,1},{0,-1} };
ll n;
ll ans = 0;
ll dp[250];
int main()
{
int kase;
scanf("%d",&kase);
rep(i,5,200) dp[i] = i/2 - (i%2==0); //预处理,偶数减去一个含相同项的。
while(kase--)
{
n = read(); ans = 0;
if(n<5) ans = 0; //小于5无解
else
{
rep(i,5,200) //枚举目标数
{
ll cur = dp[i] - max( 1,(i-n) )+1 ; //每次能选到的对
if(cur==1) continue;
if(cur==0) break;
ans += (cur-1)*cur*2*2*(n-4); //C(n,2)*2*2*2*(n-4)
}
}
printf("%lld\n",ans);
}
return 0;
}