B
http://acm.hdu.edu.cn/showproblem.php?pid=6462
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取模。
一个数字,表示螺旋线面积之和。
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
analysis:
在由题中的0 0 0 1 这些数字转化成一维数组中的数字的时候有点懵,想了很久,比赛结束后清醒一下想了出来,感觉可以从题中吸取点经验
所以结果乘的应该是4~~~
既然乘的是4,那么这里就要注意数组开辟空间大小的设置,在比赛的时候我开的数组大小是1万零5,但是一直都是超时,比赛后过了很久我才想到本题的范围不单单是从a到c,而是a+b到c+d,那么数组的大小要开到40004+;
刚开始的时候没有太在意对题目中给出的192600817进行取模操作,导致答案错误,在比赛的时候打表判断过,在刚开始没多久数据就已经爆了,果然,大意失荆州呀!
puts_number=abs(x[x2]-x[x1-1]+MOD)%MOD;
这是我的一个AC代码中的一行,关于这一行,包涵了我原本的错误想法,也就是首先判断开始和结束两个数的大小(前小后大),然后可能会出现负数的情况,我就直接abs了,这样就导致很大一部分数据会出错!
因为我们在judgee函数里面,使用前缀和的方法所求得的x[i](前i个数的平方和),本身就已经对MOD进行取模了,那么如果说puts_number为负数的时候,要进行的操作是+MOD,而不是取绝对值!
附AC代码:
#include<stdio.h>
#include<algorithm>
#include<string.h>
#include<math.h>
#include<queue>
#include<string>
#include<map>
#include<iostream>
const int MOD=192600817;
using namespace std;
long long a[40006];
long long x[40006];
void judgee()
{
a[0]=1;
a[1]=1;
x[0]=1;
x[1]=2;
for(int i=2;i<=40005;++i)
{
a[i]=(a[i-1]+a[i-2])%MOD;
x[i]=(x[i-1]+a[i]*a[i]%MOD)%MOD;
}
}
int main()
{
int Q;
judgee();
while(~scanf("%d",&Q))
{
while(Q--)
{
int aa,b,c,d;
scanf("%d%d%d%d",&aa,&b,&c,&d);
long long int x1=aa*4+b;
long long int x2=c*4+d;
long long puts_number;
if(x1>x2)
swap(x1,x2);
puts_number=(x[x2]-x[x1-1]+MOD)%MOD;
printf("%lld\n",puts_number);
}
}
return 0;
}
C
Problem Description
http://acm.hdu.edu.cn/showproblem.php?pid=6463
通常来说,题面短的题目一般都比较难,所以我要把题面写得很长很长。
通常来说,题面短的题目一般都比较难,所以我要把题面写得很长很长。
通常来说,题面短的题目一般都比较难,所以我要把题面写得很长很长。
鸽子数字由以下过程定义:从任何正整数开始,将数字替换为其各个数位的平方和,并重复该过程,直到该数字等于1。如果不能,则这个数字不是鸽子数。
例如7是鸽子数,因为7->49->97->130->10->1。(7*7=49,4*4+9*9=97,9*9+7*7=130....如此类推)
显然1是第一个鸽子数。
有Q个询问,每个询问给出一个数k,你需要输出第k个鸽子数。
Input
第一行一个Q,代表询问的个数(Q<=100000)
接下来Q行,每行一个数字k(k<150000)
Output
每行输出一个数,代表第k个鸽子数
Sample Input
2 1 2
Sample Output
1 7
比赛的时候脑子抽了,无限循环于判断1-60个数字哪个数字是鸽子数,哪个数字不是鸽子数,而没有找规律
后来对每个数字都进行计算,发现只要这个数不是鸽子数,那么在按照题目中给出的条件进行操作的时候,就会出现89,对,就是这么神奇~~~~~~
#include<stdio.h>
#include<algorithm>
#include<string.h>
#include<math.h>
#include<queue>
#include<string>
#include<map>
#include<iostream>
using namespace std;
long long number[150005];
int cnt;
void judgee()
{
for(long long i=1;;++i)
{
long long int m=i;
while(m!=1&&m!=89)
{
long long int x=m;
m=0;
while(x!=0)
{
m+=(x%10)*(x%10);
x/=10;
}
}
if(m==1)
{
number[cnt++]=i;
if(cnt==150001)
break;
}
else
continue;
}
}
int main()
{
judgee();
int Q;
cin>>Q;
while(Q--)
{
int k;
cin>>k;
printf("%lld\n",number[k-1]);
}
return 0;
}
送给我的话:复习的时候可以再看看对是否是鸽子数的判断。
简单数学题
Problem Description
已知
F(n)=∑i=1n(i×∑j=inCij)
求 F(n) mod 1000000007
Input
多组输入,每组输入占一行,包含一个整数n(1 <= n <= 1e18)。
数据不超过300000组。
Output
对于每组输入,输出一行,包括一个数代表答案。
Sample Input
5
100
Sample Output
129
660756544
一开始在做的时候疯狂超时,后来想了想,这道题的数据范围是1e18,如果说直接for循环计算2的n次方的话,很不切合实际,那么这道题就应该使用快速幂的方法!
由前几个数据找到了规律~~~~~
代码如下:
#include<cstdio>
#include<algorithm>
using namespace std;
const long long mod=1000000007;
long long int c,n;
long long er(long long x,long long y)
{
if(!y) return 1;
long long temp=er(x,y/2);
if(y%2) return temp*temp%mod*2%mod;
return temp*temp%mod;
}
int main()
{
while(~scanf("%lld",&n))
{
printf("%lld\n",(1+((n-1)%mod)*er(2,n)%mod)%mod);
}
return 0;
}