2059: Water Problem
Submit Page Summary Time Limit: 1 Sec Memory Limit: 128 Mb Submitted: 561 Solved: 189
Description
一条‘Z’形线可以将平面分为两个区域,那么由N条Z形线所定义的区域的最大个数是多少呢?每条Z形线由两条平行的无限半直线和一条直线段组成
Input
首先输入一个数字T(T<100),代表有T次询问 每次询问输入一个数字N(N<1e8),代表有N条Z形线
Output
对于每次询问,在一行输出N条‘Z’形线所能划分的区域的最大个数为多少
Sample Input
2 1 2
Sample Output
2 12
Hint
Source
Author
csutsz
这些折线,直线什么的规律都一样的,就是推出来的公式有点不同 ,就不具体讲了,递推表达式:f[i]=f[i-1]+9*(i-1)+1,得出公式
:n*(n - 1) * 9 / 2 + 1 + n
#include<cstdio>
int main() {
int t;
scanf("%d", &t);
while(t--)
{
long long n;
scanf("%lld", &n);
printf("%lld\n", n*(n - 1) * 9 / 2 + 1 + n );
}
}
刚开始的时候就推出来了个递推表达式,然后直接打表,结果数组太大re,才发现n是1e8,就算不re也会tle,然后想到可以矩阵快速幂直接算答案,A了,但是写了挺久的,后来和别人讨论才知道原来可以直接推公式
下面是矩阵快速幂的
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
typedef long long LL;
using namespace std;
const int maxn=1e8+11;
const int mod=10056;
//LL f[maxn];
struct Matrix
{
LL m[3][3];
}ans,shu;
Matrix Mul(Matrix a,Matrix b)
{
Matrix c;
memset(c.m,0,sizeof(c.m));
for(int i=0;i<3;i++)
for(int j=0;j<3;j++)
for(int k=0;k<3;k++)
c.m[i][j] += a.m[i][k]*b.m[k][j];
return c;
}
Matrix fastm(Matrix a,int n)
{
Matrix res;
memset(res.m,0,sizeof(res.m));
res.m[0][0] = res.m[1][1] = res.m[2][2] = 1;
while(n)
{
if(n&1)
res = Mul(res,a);
n>>=1;
a = Mul(a,a);
}
return res;
}
Matrix MPow(Matrix a,int n) //第二种写法,慎用,易RE
{
if(n == 1)
return a;
Matrix res = fastm(a,n/2);
res = Mul(res,res);
if(n&1)
res = Mul(res,a);
return res;
}
int main()
{
int n;
// init();
int T;
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
shu.m[0][0]=1;shu.m[0][1]=0;shu.m[0][2]=0;
shu.m[1][0]=9;shu.m[1][1]=1;shu.m[1][2]=0;
shu.m[2][0]=1;shu.m[2][1]=1;shu.m[2][2]=1;
ans=fastm(shu,n-1);
printf("%lld\n",ans.m[0][0]*2+ans.m[1][0]+ans.m[2][0]);
}
return 0;
}