求一个数的相反数算法

求一个数的相反数算法(inverse to X modulo (1 << MOD))
(相反数的定义是:求Y 使(X * Y) mod (1 << MOD) ==  1)

/*
 */param x X:inverse to X modulo (1 << MOD)
 */param mod MOD:inverse to X modulo (1 << MOD)
 */return the inverse number
 */
static unsigned long inverse (unsigned long x, int mod)

 unsigned long mask = ((unsigned long) 1 << (mod - 1) << 1) - 1;
 printf("mask=%lu,%x/n",mask,mask);
 unsigned long rslt = 1;
 int i;
 for (i = 0; i < mod - 1; i++)
  {  
  rslt = (rslt * x) & mask;  
  x = (x * x) & mask;
  //printf("%d) rslt=%lu/tx=%lu/n",i,rslt,x);
 } 
 return rslt; 
}

一般的算法都是用Euclidean的逆步骤去解,但是这个算法不是。这个算的基本原理如下:
X为奇数时,存在0<i<mod,使得X^(2^i) % (2^mod) = 1
(这个我证明了一下,不难,我就不贴了)
即:X,X^2,X^4,X^8,X^16……X^2^(mod-1)里面一定有一个数,使X^(2^i) % (2^mod)=1
然后,X^(2^i-1)即为所求。

还有一个定理需要说明:X*Y % a =(X % a)*(Y % a) % a,
也就是:两个数相乘后取模,等于取模后相乘,再取模。这个也不用证明了吧。

注意算法里的mask=2^mod - 1 ,二进制表示为111111(mod个1)
ps.不知道为什么写成 1<<(mod-1)<<1 - 1,而不直接写成 1<<mod - 1
进行a & mask操作,相当于进行a%(2^mod)操作。
这是用&操作进行的优化。

现在看循环里的操作就比较简单了:
(先不看rslt)
循环里的X不断自乘,然后后取模,
所以X的值依次为
X(初始值)

附测试函数:
int main()
{
 unsigned long x;
 int mod;
 scanf("%lu %d,",&x,&mod);
 printf("%lu ",inverse(x,mod));
 return 0;
}
 

在 Java 中,贪婪算法通常用于解决一种优化问题,比如 n 位(例如整)删除 m 个字以得最大或最小值的问题。这种问题被称为“最小/最大失效率”问题,也称为“卡特兰”问题。贪婪策略在这里并不总是最优解,因为删除某些特定位置的字可能会导致后续删除更困难。 经典的贪心算法思路通常是尝试每次删除能够带来最大收益的位置,即当前值最大或最小,然后递归处理剩下的部分。然而,对于这个问题,直接应用贪婪算法可能存在局部最优解而非全局最优解。例如,对于一些特定的 n 和 m,直接删除最大的几位可能会导致剩余的部分无法构成有效的整一个常用的解决方案是回溯法,也称为动态规划。通过枚举所有可能的删除组合,计算每个组合下的结果,并保存最佳解。这是一种非贪婪策略,它确保了找到的是整个问题空间中的最优解。 这里是一个简单的伪代码示例: ```java public int maxLoss(int num, int m) { List<Integer> digits = new ArrayList<>(); while (num > 0) { digits.add(num % 10); num /= 10; } int[][] dp = new int[digits.size() + 1][m + 1]; for (int i = 1; i <= digits.size(); i++) { for (int j = 0; j <= m; j++) { if (j == 0) { dp[i][j] = Integer.MAX_VALUE; } else { // 删除当前位,考虑下一位是否也要删除 int removeCurrent = digits.get(i - 1); int noRemove = dp[i - 1][j]; dp[i][j] = Math.min(dp[i - 1][j], removeCurrent + dp[i - 1][j - 1]); } } } return dp[digits.size()][m]; } // 获取最小失效率,即相反情况 public int minLoss(int num, int m) { // 对于 minLoss,只需对 maxLoss 的计算取反即可 return -maxLoss(num, m); } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值