【问题标题】:Google Code Jam 2008 Round 1A Q 3Google Code Jam 2008 第 1A Q 3 轮
【发布时间】:2013-09-23 16:21:50
【问题描述】:

对于 2008 年 google codejam 中的 problem statement:第 1A 轮问题 3

在这个问题中,你必须找到最后三位数字 数字的小数点 (3 + √5)n.

例如,当 n = 5 时,(3 + √5)5 = 3935.73982... 答案是 935。

对于 n = 2,(3 + √5)2 = 27.4164079...答案是 027。

我的解决方案基于 T(i) = 6*T(i-1) - 4*T(n-2) + 1,其中 T(i) 是 n=i 的整数部分为下面:

#include<stdio.h>
int a[5000];
main(){
    unsigned long l,n;
    int i,t;
    a[0]=1;
    a[1]=5;
    freopen("C-small-practice.in","r",stdin);
    scanf("%d",&t);
    for(i=2;i<5000;i++)
            a[i]=(6*a[i-1]-4*a[i-2]+10001)%1000;
    i=t;
    for(i=1;i<=t;i++){

            scanf("%ld",&n);
            printf("Case #%d: %.3d\n",i,a[(int)n]);
    }
    fclose(stdin);
}

a[i]=(6*a[i-1]-4*a[i-2]+10001)%1000; 行中我知道会有整数溢出,但我不知道为什么加上 10,000 我得到了正确的答案。 我正在使用 GCC 编译器,其中 sizeof(int)=4

谁能解释发生了什么?

【问题讨论】:

    标签: algorithm integer-overflow


    【解决方案1】:

    首先,线

    a[i]=(6*a[i-1]-4*a[i-2]+10001)%1000;
    

    实际上不应导致任何溢出,因为您将所有先前的值保持在 1000 以下。

    其次,您是否考虑过如果6*a[i-1]-4*a[i-2]+1 为负数会发生什么?模运算符不必总是返回正值;它也可以返回负值(如果你要划分的东西本身就是负数)。

    通过添加 10000,您可以确保无论之前的值是什么,该表达式的值都是正数,因此 mod 将给出一个正整数结果。

    扩展第二点,这里是 C99 规范的 6.5.5.6:

    整数除法时,/运算符的结果是代数 商与丢弃的任何小数部分。如果商 a/b 是 可表示,表达式 (a/b)*b + a%b 应等于 a。

    “丢弃”一词旁边的注释指出/“向零截断”。因此,要使第二句为真,a % ba 为负时的结果本身必须为负。

    【讨论】:

    • 没问题,制作简单;我记得我第一次开始使用%时被它咬过很多次。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-10
    相关资源
    最近更新 更多