题目链接
2 1 2
Case #1: 2 Case #2: 19
题意:由两条平行的射线和两条线段构成的类似 ‘M’ 的图形,现在有n个,任意放,问最多能将平面分成多少个区域?
题解:由欧拉公式可知:对于一个几何结构的点数+面数-边数+1=空间维数
这题本来是个二维图,因为有射线,我们可以虚拟一个无穷远的点,把图形看成三维。那么问题就是求新图形的面数。
面数=边数+空间维数-点数-1;
n个‘M’相交,边数最多为:
一条线最多被切成:4*(n-1)+1 条线段
每个‘M’4条线段,n个‘M’的总线段就是:
16*n^2-12*n
空间维度为:3
点数最多为:
两个‘M’相交最多产生 16个点,一个‘M’自身有3个点,所有’M‘两两相交的话,再加上无穷远那个点,总点数是:
16*n*(n-1)/2+3*n+1=8*n^2-5*n+1
最后可得面数=8*n^2-7*n+1。
数据很大要用高精度,由于最后答案最大是10^24的数量级,也可以用两个long long 来拼成一个大整数。
高精度解法的代码:
//#pragma comment(linker, "/STACK:102400000,102400000") #include<stdio.h> #include<queue> #include<iostream> #include<algorithm> #include<string.h> #include<string> #include<math.h> #include<stack> typedef long long LL; using namespace std; struct BigInt { const static int mod = 10000; const static int DLEN = 4; int a[600],len; BigInt() { memset(a,0,sizeof(a)); len = 1; } BigInt(long long v) { memset(a,0,sizeof(a)); len = 0; do { a[len++] = v%mod; v /= mod; }while(v); } BigInt(const char s[]) { memset(a,0,sizeof(a)); int L = strlen(s); len = L/DLEN; if(L%DLEN)len++; int index = 0; for(int i = L-1;i >= 0;i -= DLEN) { int t = 0; int k = i - DLEN + 1; if(k < 0)k = 0; for(int j = k;j <= i;j++) t = t*10 + s[j] - '0'; a[index++] = t; } } BigInt operator +(const BigInt &b)const { BigInt res; res.len = max(len,b.len); for(int i = 0;i <= res.len;i++) res.a[i] = 0; for(int i = 0;i < res.len;i++) { res.a[i] += ((i < len)?a[i]:0)+((i < b.len)?b.a[i]:0); res.a[i+1] += res.a[i]/mod; res.a[i] %= mod; } if(res.a[res.len] > 0)res.len++; return res; } BigInt operator *(const BigInt &b)const { BigInt res; for(int i = 0; i < len;i++) { int up = 0; for(int j = 0;j < b.len;j++) { int temp = a[i]*b.a[j] + res.a[i+j] + up; res.a[i+j] = temp%mod; up = temp/mod; } if(up != 0) res.a[i + b.len] = up; } res.len = len + b.len; while(res.a[res.len - 1] == 0 &&res.len > 1)res.len--; return res; } void output() { printf("%d",a[len-1]); for(int i = len-2;i >=0 ;i--) printf("%04d",a[i]); printf("\n"); } }ans; int main() { int t,cas=1; LL n; scanf("%d",&t); while(t--) { scanf("%I64d",&n); ans=BigInt(8*n-7)*BigInt(n)+BigInt(1); printf("Case #%d: ",cas++); ans.output(); } return 0; }
用两个long long 拼大整数的做法如下:
//#pragma comment(linker, "/STACK:102400000,102400000") #include<stdio.h> #include<queue> #include<iostream> #include<algorithm> #include<string.h> #include<string> #include<math.h> #include<stack> typedef long long LL; using namespace std; const int mod=1000000; LL n; int main() { int t,cas=1; scanf("%d",&t); while(t--) { scanf("%I64d",&n); LL ltem,rtem; ltem=(8*n-7)/mod,rtem=(8*n-7)%mod; LL lans=0,rans; rans=(rtem*n)%mod; lans=ltem*n+(rtem*n)/mod; rans=(rans+1)%mod; lans=lans+(rans+1)/mod; printf("Case #%d: ",cas++); if(lans) { printf("%I64d%06I64d\n",lans,rans); } else printf("%I64d\n",rans); } return 0; }