解锁成就:死于看成平面几何题
题目描述
将一个边长为 N 的正方形裁剪成四个直角三角形。注意面积不能为 0。
三个必要的切割中的两个始终从一个角落G进行(图中G位于A,实际上也可以是B、C、D),第三次切割必须垂直于前面两个之一(在图中,AE部分垂直于EF部分)。
切割机仅接受整个坐标值,这意味着N必须是整数的,并且点E和F的坐标必须是整数的。 有时候这可能是不可能的。
编写一个程序,根据给出的 N ,确定是否可以将四边形的正方形三角形切割成四个矩形三角形,如果可能的话,可以采用多少种方法来完成。
输入格式
每行一个整数 N,以 0 结尾
输出格式
每行一个整数表示方案数,方案不同当且仅当 E、F、G 的坐标不同
样例数据
input
10
20
100
32
0
output
0
8
72
24
数据范围
对于 40% 的数据,n≤10^7
对于另 10% 的数据,n 是质数
对于 100% 的数据,n≤10^14,不超过5组数据
时间限制 1 s
空间限制 512 MB
题目分析
毕竟信息用的数学和数学竞赛还是不大一样啊……
这里非常重要的一步是从a=(n-x)*x/n想到划分剩余类。
于是最朴素的解法就是枚举x.
注意到x有一个充要的命题:
注意是向上取整。
由于x的取值是$[1,n)$,所以x的个数就是:
化简一下可以得到:
就可以了。
1 #include<bits/stdc++.h> 2 typedef long long ll; 3 const int maxn = 10000000; 4 5 int pr[800035]; 6 bool vis[10000035]; 7 ll n,cnt; 8 9 void makePrime() 10 { 11 for (int i=2; i<=maxn; i++) 12 { 13 if (!vis[i]) pr[++pr[0]] = i; 14 for (int j=1; j<=pr[0]&&pr[j]*i<=maxn; j++) 15 { 16 vis[pr[j]*i] = 1; 17 if (i%pr[j]==0) break; 18 } 19 } 20 } 21 ll qmi(ll a, ll b) 22 { 23 ll ret = 1; 24 while (b) 25 { 26 if (b&1) ret = ret*a; 27 b >>= 1, a = a*a; 28 } 29 return ret; 30 } 31 int main() 32 { 33 register int i; 34 register ll tmp; 35 makePrime(); 36 while (scanf("%lld",&n)!=EOF&&n) 37 { 38 cnt = 1; 39 for (i=1; pr[i]<n&&i<=pr[0]; i++) 40 { 41 tmp = 0; 42 while (n%pr[i]==0) tmp++, n /= pr[i]; 43 cnt *= qmi(pr[i], tmp/2); 44 } 45 printf("%lld ",cnt*8ll-8ll); 46 } 47 return 0; 48 }
END