【杭电】-人类史上最大最好的希望事件

题目连接:人类史上最大最好的希望事件

这题就是个斐波那契的一个变形数列,只不过是把每一个数变成它的平方,再根据题意做就可以了。挺简单的不过要注意的是这些数非常的大,要不断的对题目给出的数进行取余。由于数据很大,所以要进行打表,打表的方式是打出这个数之前的所有数的和,存放在一个数组里,最后求的时候只要做个差就行了,但要注意的是作差时可能为负数,所以加上mod在对mod取余。

Problem Description

作为CNCS的半壁江山,狗哥常常在宇宙中心邵阳眺望黄浦江,夜晚的星空总是迷人,有时候还能见到彗星滑落。

狗哥是幸运的,他在两秒钟内看到了十七颗彗星划过天际,作为打ACM的学者,自然不会有「稳定-1」情况。他开始研究彗星运动的轨迹,发现他们都遵照斐波那契螺旋线在运动着。

尤里卡!狗哥觉得这就是找寻「生命,宇宙和一切的终极答案」的精要所在,但是怎么表示呢?狗哥觉得求取斐波那契螺旋线经过的一个个方格的面积之和就是公式的表现。

例如下图,螺旋线每划过一个方格,都转过了四分之一圈。如果我们以四分之一圈为单位,那么我们用类似带分数的形式表示螺旋线转动的起点和终点。例如,0+0 到 0 + 1 意即从第一个方格转到第二个方格,划过了前两个方格,他们的面积之和为2(1+1)。同理,0+0 到 1+0 划过了前五个方格,他们的面积之和为40(1+1+4+9+25)。
 



但是聪明的狗哥需要一个程序去获得指定范围内的螺旋线面积之和,狗哥给了你一首「希望之花」的时间,而他需要利用这个时间去打出四暗刻单骑。如果你能完成这个程序,狗哥会封你为格拉摩根伯爵

Input

 

不定组数据。

首先输入一个整数Q,代表狗哥询问次数。

接下来Q行,每行四个整数a,b,c,d,代表狗哥想求 a+b 到 c+d 之间的螺旋线面积之和。

1<= Q <= 10000

0<= a,c <= 10000

0 <= b,d <= 3

结果对192600817取模

 

Output

 

一个数字,表示螺旋线面积之和。

 

Sample Input

4

0 0 0 1

0 0 1 0

1 2 2 1

1 1 0 3

4

0 0 0 1

0 0 1 0

1 2 2 1

1 1 0 3

Sample Output

 2

40

4791

98

2

40

4791

98

代码如下:

#include<stdio.h>
#include<string.h>
#include<math.h>
#include<stdlib.h>
#include<algorithm>
using namespace std;
typedef long long ll;
ll dis[10101][4];
ll vis[1010100];
int main()
{
	ll p=2,sum;
	ll mod=192600817;
	dis[-1][3]=0;
	vis[1]=1;vis[2]=1;
	for(int i=3;i<=1001000;i++)
	{
		vis[i]=(vis[i-1]+vis[i-2])%mod;
	}
	memset(dis,0,sizeof(dis));
	for(ll i=0;i<=10010;i++)
	{
		sum=0;
		for(ll j=0;j<=3;j++)
		{
			if(i==0&&j==0)
			{
				dis[i][j]=1;
				continue;
			}
			if(i==0&&j==1)
			{
				dis[i][j]=2;
				continue;
			}
			p=p+1;
			sum=(vis[p]*vis[p])%mod;
			if(j==0)
			dis[i][j]=(dis[i-1][3]+sum)%mod;
			else
			dis[i][j]=(dis[i][j-1]+sum)%mod;
		}
	}
	
	ll n;
	while(~scanf("%lld",&n))
	{
		ll a,b,a1,b1;
		for(ll i=0;i<n;i++)
		{
			scanf("%lld%lld%lld%lld",&a,&b,&a1,&b1);
			if(a<a1)
			{
				if(b==0)
					printf("%lld\n",(dis[a1][b1]-dis[a-1][3]+mod)%mod);
				else
				printf("%lld\n",(dis[a1][b1]-dis[a][b-1]+mod)%mod);
			}
			else if(a==a1) 
			{
				if(b<=b1)
				{
					if(b==0)
						printf("%lld\n",(dis[a1][b1]-dis[a-1][3]+mod)%mod);
					else
					printf("%lld\n",(dis[a1][b1]-dis[a][b-1]+mod)%mod);
				}
				else
				{
					if(b1==0)
					printf("%lld\n",(dis[a][b]-dis[a1-1][3]+mod)%mod);
					else
					printf("%lld\n",(dis[a][b]-dis[a1][b1-1]+mod)%mod);
				}
			}
			else if(a>a1)
			{
				if(b1==0)
				printf("%lld\n",(dis[a][b]-dis[a1-1][3]+mod)%mod);
				else
				printf("%lld\n",(dis[a][b]-dis[a1][b1-1]+mod)%mod);
			}
		}
	}
	return 0;
}

 

 

 

 

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
杭州电子科技大学在线评测系统(杭电OJ)中的题目1000-1100是一系列编程题,我将分别进行回答。 1000题是一个简单的入门题,要求计算两个整数的和。我们可以使用一个简单的算法,读取输入的两个整数,然后将它们相加,最后输出结果即可。 1001题是一个稍微复杂一些的题目,要求实现字符串的逆序输出。我们可以使用一个循环来逐个读取输入的字符,然后将这些字符存储在一个数组中。最后,我们可以倒序遍历数组并将字符依次输出,实现字符串的逆序输出。 1002题是一个求最大公约数的问题。我们可以使用辗转相除法来解决,即先求出两个数的余数,然后将被除数更新为除数,将除数更新为余数,直至两个数的余数为0。最后的被除数就是最大公约数。 1003题是一个比较简单的排序问题。我们可以使用冒泡排序算法来解决,即每次比较相邻的两个元素,如果它们的顺序错误就交换它们的位置。重复这个过程直至整个数组有序。 1100题是一个动态规划问题,要求计算给定序列中的最长上升子序列的长度。我们可以使用一个数组dp来保存到达每个位置的最长上升子序列的长度。每当遍历到一个位置时,我们可以将其和之前的位置比较,如果比之前位置的值大,则将其更新为之前位置的值加1,最后返回dp数组的最大值即可。 以上是对杭电OJ1000-1100题目的简要回答,涉及了一些基本的编程知识和算法思想。希望对您有所帮助。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值