2014-10-18 70 views
0

所以,我有以下问题:C++长长的诠释

会有下个月在全市大型会议。通常朋友 倾向于到达并一起注册,所以他们最后也会坐在对方 和他们已经知道的人聊天。在 为了让事情有点发挥,会议组织者想出了一个系统来“洗牌”服务员的顺序,并因此,让他们 结识新朋友。

该系统的工作原理如下:第一个到达 会议注册的人获得一张票号为a1,组织者随机选择 。以下每个人到达后会得到一张新号码,其号码为ai =(ai - 1×31334)mod 31337,并且在队列中找到其相应的位置 ,在最后一个人的后面 的号码小于或等于AI。这意味着队列中的票号 应该始终按顺序排列,并且如果已有很多具有相同号码的人,则最近到达的应该是该组中的最后一个 。

你的任务是编写一个计算机程序,它将帮助服务员 找到他们在队列中的正确位置。

示例给定初始票证号码a1 = 7546,在第6个人到达的队列中找到位置 。所以这里的输入是[7546, 6]。

讨论:第一个到达的人获得票a1 = 7546和 站在队列的前面。第二个人获得门票a2 =(7546×31334)mod 31337 = 8699,因此站在队列中的第二个位置。第三个人到达然后获得票号 ,其中号码a3 =(8699×31334)mod 31337 = 5240,因此,得到 跳过队列并站在位置1,将其他人 移动到队列一位置到背部。也就是说,队列如下所示:

1:5240(3),2:7546(1),3:8699(2)其中票号为 递增顺序,parentesis中的数字为原始参与者到达会议的 。

继续这个顺序,第四,第五和第六个参与者 将得到票号a4 = 15617,a5 = 15823和a6 = 15205;因此 队列将如下所示:

1:5240(3),2:7546(1),3:8699(2),4:15205(6),5:15617(4),6 : 15823(5)即第6个到达的人站在队列中的 位置4。

答:4

而下面的C++代码:

#include <iostream> 
using namespace std; 
int main() 
{ 
    int n, i, poz, ok; 
    long long int a, v[100], aux; 
    cout << "v[1]= "; cin >> v[1]; 
    cout << "n= "; cin >> n; 
    for (i=2; i<=n; i++) 
     v[i]=(v[i-1]*31334)%31337; 
    a=v[n]; 
    do 
    { 
     ok=0; 
     for (i=1; i<n; i++) 
      if (v[i]>v[i+1]) 
      { 
       aux=v[i]; 
       v[i]=v[i+1]; 
       v[i+1]=aux; 
       ok=1; 
      } 
    }while (ok==1); 
    for (i=1; i<=n; i++) 
     if (v[i]==a) 
      poz=i; 
    cout << poz; 
    return 0; 
} 

它显示了正确的事情,对于小的数字,但是当我进入较大的下面就是我的问题,因为它只是打破。 例如,[7253,10]显示4,[24284,10]显示1,但输入[12879,505]时显示中断。 有什么想法?

+1

您可以通过使用范围检查数字来检查数字范围是否被超出。 C++没有内置的或标准的库支持,但它很容易实现(虽然有些工作)。也许Boost lib有一些支持,或者说,只是谷歌。 – 2014-10-18 09:04:44

+0

整数溢出 – Creris 2014-10-18 09:14:34

+1

好的隐藏变量名称和未命名的显式循环。 – rightfold 2014-10-18 09:16:42

回答

1

即使不打算在你的代码,我可以说,整数溢出不应该是一个问题,即使是signed int S:

31337² = 982,007,569这是111010100010000011111100010001,一个30位的数字。

因此,在这里不应该超过MAX INT,即(2^31)-1 = 2,147,483,647。 就像一块琐事一样,long long int将支持高达(2^63)-1 = 9,223,372,036,854,775,807的数字。

需要现在要做的事情就是调试代码...

按你的错误 - 我认为这个问题是您定义的arrav v 100的尺寸,并试图找到第505元 - 这本质上是非法的内存访问,因此是不可预测的。 你对你自己的代码:)从所有

除了做一个缓冲区溢出,我建议你花一些时间整理你的代码 - #define或为您的常量添加const值(数组大小,31337,31334等等) 请记住,C++中的数组以v[0]开头,而不是v[1] - 无论文字如何描述。这是个错误。 封装forif语句,即使您只有一个表达式跟随它们,或者在未来添加代码时,您会忘记它们,并有一个“有趣”的时间来调试它。

通常建议 - 保存自己的一些悲痛,并使用尤达盒的习惯:1 == ok代替ok == 1因为笔误把它变成ok = 1会导致你一个非常讨厌的错误。

1

你应该考虑使用一个向量并推回值。

但是你要走出你的阵列。您创建了一个大小为100的数组,并且您正尝试在上次测试中使用505个空间。

因此,要么使用矢量和push_back你的值或增加你的数组的大小。为了便于使用,我会推荐该载体。

下面是我扔在一起解决您的问题,使用容器和STL函数为您完成大部分工作。希望这可以帮助你。 =)

#include <iostream> 
#include <vector> 
#include <algorithm> 

using namespace std; 

using LONG64 = long long; 

const int MULTIPLIER = 31334; 
const int MOD = 31337; 

int main() 
{ 
    vector<LONG64> ticket; 

    cout << "v[1]= "; 
    LONG64 seed; 
    cin >> seed; 
    ticket.emplace_back(seed); 

    cout << "n= "; 
    int queue_spot; 
    cin >> queue_spot; 

    for (auto i = 1; i <= queue_spot; ++i) { 
     auto seed_number = (ticket[i - 1] * MULTIPLIER) % MOD; 
     //cout << "\nseed_number " << seed_number; 
     ticket.emplace_back(seed_number); 
    } 

    LONG64 person_ticket_number = ticket[queue_spot - 1]; 

    cout << "\nPerson's ticket number " << person_ticket_number; 

    sort(ticket.begin(), ticket.end()); 

    auto spot = find(ticket.begin(), ticket.end(), person_ticket_number); 

    cout << "\nPerson is in spot " << (spot - ticket.begin()) + 1 << endl; 

    system("PAUSE"); 
    return 0; 
}