使用模数计算

时间:2013-09-16 20:14:01

标签: c algorithm operators modular-arithmetic

我正在解决一个问题: 用户输入3个树高度和树高限制。然后程序计算要删除的树的数量。

示例输入:

 Tree1: 14
 Tree2: 7
 Tree3: 16

 Tree limit: 11

示例输出:

 Amount to remove: 8

这对我来说通常不会太糟糕,虽然我还是初学者,但问题是,我将在没有if语句的情况下计算它。我必须使用Modulus来计算。我花了很长时间研究和尝试不同的东西,但我似乎无法得到它?有任何想法吗?

8 个答案:

答案 0 :(得分:5)

您正在寻找的表达方式是:

tree[i] % max % tree[i];

tree[i]大于max时:
示例:16和11

16 % 11 = 5
5 % 16 = 5

tree[i]小于max时: 示例:7和11

7 % 11 = 7
7 % 7 = 0

int main(void)
{
    int tree[3] = {0};
    int max = 0;
    int cut = 0;

    printf("Max Height: "),
    scanf("%d", &max);

    for(int i=0; i<3; ++i)
    {
        printf("Tree%d: ",i+1),
        scanf("%d", &tree[i]);
    }

    for(int i=0; i<3; ++i)
    {
        cut += (tree[i] % max) % tree[i];
    }
    printf("Amount to remove: %d\n", cut);

    getchar();
    return 0;
}

2015年8月(距离原帖近2年),我决定重温这个问题,并提出一个通用的解决方案。

看起来有点工作,但完整的表达是:

int cut = (tree % max % tree) + !!(tree/max) * (tree/max - 1) * max;

<强>示例:

| Tree | Max | Expression      | Answer |
|    4 |  11 | 0 + 0 * -1 * 11 |      0 |
|   47 |  11 | 3 + 1 * 3 * 11  |     36 |

注意:我的使用!! (double-not)几乎只是一个C / C ++构造。可能无法使用其他语言。

答案 1 :(得分:5)

以下是一般解决方案:

#include <stdio.h>

#define CUTAMOUNT(tr, lim) (tr - lim) * (((2 * tr) - ((2 * tr) % (tr + lim))) / (tr + lim - 1))

int main (int argc, char **argv) {

    int tree1 = 14;
    int tree2 = 7;
    int tree3 = 16;
    int limit = 11;

    int cutamounttotal = 0;

    cutamounttotal += CUTAMOUNT(tree1, limit);
    cutamounttotal += CUTAMOUNT(tree2, limit);
    cutamounttotal += CUTAMOUNT(tree3, limit);

    printf("Amount to remove: %d\n", cutamounttotal);

    return 0;
}
  • 没有分支
  • 没有循环
  • 无条件
  • 没有三元运作
  • 无按位操作
  • 无逻辑运算

仅算术运算。诀窍是要理解%是唯一可以创建步骤的算术运算符。操作数必须适当调整大小,以确保步骤只发生在我们想要的地方,而不是其他地方。然后我们可以利用该步骤来提供所需的结果。

答案 2 :(得分:1)

你可以只使用绝对值函数(abs),除法,减法,加法。

Tree1: 14
Tree2: 7
Tree3: 16

Tree limit: 11

14-11=3 ----->3+abs(3)=6  ----------> 6/2 =3
7-11=-4 ----> -4 + abs(-4)=0 -------------> 0/2=0
16-11=5 -----> 5+abs(5)=10 ------------> 10/2 = 5
...
...
...
3+5 = 8 :D

上面的文字显示了如何将较小的值转换为零。因此,只有更大的值才具有附加效果。

如果你不能使用abs()那么你可以移动左移+右移组合以获得绝对值。 但这可能是未定义的行为。结果是为签名值的右移定义的实现。

答案 3 :(得分:1)

我对自己提出这么多想法感到有些失望,但话虽这么说,我还是会站出来对所有n > 0表示没有通用解决方案。不使用if语句,或者不使用其他类型的技巧来模拟一个。如果有人证明我错了,我会很乐意吃掉我的话。

对于每棵树,明显而正确的解决方案是:

cut = max(height - limit, 0);

相当于:

if ( height - limit > 0 ) {
   cut = height - limit;
} else {
   cut = 0;
}

或者:

if ( height > limit ) {
   cut = height - limit;
} else {
   cut = 0;
}

最简单的方法(除了使用max()函数之外)在没有实际明确使用if语句的情况下模拟它是:

cut = (height - limit) * (height > limit);

因为height > limit会在适当的时间评估为10

您也可以使用while循环进行模拟:

cut = 0;
while ( height > limit ) {
   cut = height - limit;
   break;
}

使用三元运算符是声称不使用if的最明显的方法。可能还有其他一些技巧搞乱,但故事是一样的。

可以修改这些方法中的任何一种来使用模运算符作为问题,但所有实现的方法都是使更简单的算法更复杂。

我怀疑abelenky的答案中的方法是正在寻找的方法,可能是问题的最佳整体解决方案,尽管这只适用于0 < n < 2 * limit

答案 4 :(得分:0)

假设您已经将3个树高中的数据读入数组:

int trees[3];
int limit = 11;
int i;
int cut = 0;
for (i = 0; i < 3; i++) {
    int cut += trees[i] > limit
             ? (trees[i] / limit - 1) * limit + trees[i] % limit
             : 0;
}
printf("Amount to remove: %d\n", cut);

答案 5 :(得分:0)

[编辑] - 树的所有值的解决方案,使用%运算符,但不使用三元运算符:

#include <stdio.h>

#define MAX 11

int modsum(int a, int b, int c) ;

int main()
{
    int results;
    results = modsum(25, 7, 16);
    return 0;
}

int modsum(int a, int b, int c)
{
    int i, suma, sumb, sumc;

    i=0;
    while(a > 2*MAX)
    {
        i++;
        a -= MAX;
    }
    suma = (i*MAX)+(a%MAX%a);

    i=0;
    while(b > 2*MAX)
    {
        i++;
        b -= MAX;
    }
    sumb = (i*MAX)+(b%MAX%b);

    i=0;
    while(c > 2*MAX)
    {
        i++;
        c -= MAX;
    }
    sumc = (i*MAX)+(c%MAX%c);


    return suma+sumb+sumc;

}

答案 6 :(得分:0)

假设您被允许使用*/>,您可以这样做:

#include <stdio.h>

int main()
{
  int trees[3] = {24, 7, 16};
  int limit = 11;
  int allowedRemainder = 0;
  int mod = 0;
  int modCount = 0;
  int i;
  for (i = 0; i < 3; ++i)
  {
    allowedRemainder = (trees[i] / limit) - 1;
    mod = trees[i] % limit;

    modCount += (allowedRemainder > 0) * (allowedRemainder * limit) +
                (allowedRemainder >= 0) * mod;
    printf("Loop %d: mod = %d\n", i, modCount);
  }
  printf("Amount to remove: %d\n", modCount);
  return 0;
}

(allowedRemainder > 0) * (allowedRemainder * limit)表示如果我们至少有limit次允许,请将limit的倍数添加到modCount(allowedRemainder >= 0) * mod表示如果我们有limit以上,请将余数添加到modCount

[Sample Code]

答案 7 :(得分:0)

树高在数组中,因为我懒得制作3个变量 它根据要求使用模运算符。

#include <stdio.h>

int main(void)
{
  int tree_h[]={14,7,16};
  int limit=11;
  int i;
  int remove=0;

  for(i=0;i<3;i++)
  {
    remove+=(tree_h[i]>limit)*(tree_h[i]%limit);
  }
  printf("Amount to remove: %d\n", remove);

  return 0;
}