2018/4/17双线程dp、多边形面积求法、N阶乘最后非零位、博弈(今天本来的博客)

版权声明:抱最大的希望,为最大的努力,做最坏的打算。 https://blog.csdn.net/qq_37748451/article/details/79976985

NYOJ712探索宝藏这个题就是一个典型的双线程的dp

首先,假设出发点为A 终点为B 那么,根据题目给出的条件,可以推出A->B的动态转移方程为 

dp[i][j] = max(dp[i-1][j],dp[i][j-1]) + a[i][j]; 

由于,同理可得B的情况,那么,题目的意思是A->B 然后 B -> A我们可以假设同时从A点出发,得到两条不同路

径,这个是一样的效果。所以,我们可以得到一个动态转移方程

dp[i][j][p][q] = max(dp[i-1][j][p-1][q],dp[i-1][j][p][q],dp[i][j-1][p-1][q],dp[i][j-1][p][q-1]) 

因为 每次只能移动一步,即 i+1 或j+1 那么 i+j是移动的步数 因为从A点开始移动的,经过相同的步数,肯定能得到i+j = p+q

还有一点要注意一下,这题与NYOJ 61是同类问题,但是,有一点细节要注意,最后终点的值也要算上,上面的动态方程得到的

值不包含两个A 和 B的值,因为 A是起点,所以,他的值一般是0,所以,得到最后的结果应该是 :

int sum = max(dp[m-1][n][m-1][n],dp[m-1][n][m][n-1],dp[m][n-1][m-1][n],dp[m][n-1][m][n-1]) + a[m][n]; 

一去一回可以想象成一个人从一个地方出发不过走不同的路线。


多边形面积求法:

将其分为n个三角形,并用叉乘求出所有三角形面积之和
多边形重心求法(假设质量分布均衡):
1、质量分布在每个定点上
重心坐标为(所有点横坐标和的平均, 所有点纵坐标和的平均)
2、质量完全均匀分布
先以第一个顶点为基准,分别连接p[i]、p[i+1]……(2<=i<=n),将多边形划分为若干个三角形,然
后求出所有三角形的叉积面积(可能为负!保留符号)以及重心(x1+x2+x3)/3, (y1+y2+y3)/3),
最后多边形的重心坐标就为(所有三角形重心x坐标*叉积面积的积之和/叉积面积之和,所有三角形重心y坐标*叉积面积的积之和/叉积面积之和)

1:n!的尾部的"0"全部来自因子5和因子2(一对5和2产生一个0),如果把这些因子去掉,则可符合要求(2的个数明显多于5的个数)

2:设F(n)为答案所要求的数,G(n)为1,2…n中将5的倍数的数换成1后的各项乘积,G(15)=1*2*3*4*1*6*7*8*9*
1*11*12*13*14*1(G(n)%10必不为0),则可推出以下两个公式
① n! = (n/5)! * 5^(n/5) * G(n)  ② F(n!) = F((n/5)!) * F[5^(n/5) * G(n)] (可以递归)
3:根据②可知F[5^(n/5) * G(n)] = F[G(n)/(2^(n/5))],其中G(n)/(2^(n/5))可找到规律
4:枚举可找到上述规律为Mp[20] = {1,1,2,6,4,2,2,4,2,8,4,4,8,4,6,8,8,6,8,2}(20一循环)这样就可以算出答案啦
PS:
n<=19  ----  G[n] = data[n]
n>=20  ----  G[n] = data[n%20]

n过大,这里用字符串处理


#include<stdio.h>

#include<string.h>

char str[10005];
int a[10005], Mp[20] = {1,1,2,6,4,2,2,4,2,8,4,4,8,4,6,8,8,6,8,2};  /*这个是F[5^(n/5)*G(n)]的前20(0-19)项,后面循环*/
int main(void)
{
int T, len, ret, i, c;
scanf("%d", &T);
while(T--)
{
scanf("%s", str);
len = strlen(str);
for(i=len-1;i>=0;i--)
a[len-1-i] = str[i]-'0';     /*将n的每一位存入数组a[],其中a[0]是最低位,a[len-1]是最高位*/
ret = 1;
while(len!=0)  /*用循环代替递归*/
{
c = 0;
ret = ret*Mp[a[1]%2*10+a[0]]%10;   /*"a[1]%2*10+a[0]"是计算n%20的值*/
for(i=len-1;i>=0;i--)
{
c = c*10+a[i];    /*计算n除以5之后的值,并将其存入(覆盖)a[]*/
a[i] = c/5;
c %= 5;
}
if(a[len-1]==0)     /*如果最高位是0,去掉最高位*/
len--;
}
if(strcmp(str, "1")==0 || strcmp(str, "0")==0)
printf("1\n");
else
printf("%d\n", ret);
}
return 0;
}
https://www.cnblogs.com/kuangbin/archive/2011/08/28/2156426.html
ACM博弈知识汇总



1:n!的尾部的"0"全部来自因子5和因子2(一对5和2产生一个0),如果把这些因子去掉,则可符合要求(2的个数
阅读更多
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页