欧拉Totient函数从1到N的有效和

时间:2019-08-06 04:04:11

标签: algorithm math

问题摘要

当H定义如下时,计算H:

H=0;
For (i=1; i<=n; i++) {
    For (j=1; j<=n; j++) {
        H = H + totient(i) * totient(j);
    }
}

totient(n)这是n的欧拉Totient函数。完整的问题可用here

解决方案摘要

问题给出的伪代码是一种简单的计算H的方式。在观察之后,H实际上是从1n的给定函数的总和,给定n,平方。我的解决方案是使用筛子生成最多sqrt(10^4) = 10^2的质数列表,并使用所说的筛子查找其素数并使用Euler's product formula来生成数字1到10 ^ 4的Euler Totient函数值。然后,我只需要对上述计算值求和并求平方即可得到H

here提供了筛分代码和计算欧拉Totient函数值的代码。我的代码已被在线法官接受(在添加了我所链接的代码中未包括的求和部分和平方部分之后)。

问题

我注意到欧拉的Totient函数值的总和:1, 2, 4, 6, 10, 12, 18, 22, 28, 32, 42, 46, 58, 64, 72,从i = 1i = 15。看来这可能是一些自定义的数学序列,我们可以直接计算i-th欧拉的Totient函数值,而无需使用某些数学公式将欧拉的Totient值本身求和。因此,我搜索了Google,发现了this

我感兴趣的一个特定部分是这一部分:

  

Sum_ {k = 1..n} phi(k)给出不同算术级数,该级数包含无限数量的素数,并且其差值不超过n。例如,{1k + 1},{2k + 1},{3k + 1、3k + 2},{4k + 1、4k + 3},{5k + 1,.. 5k + 4}表示10个序列。 -Labos Elemer,2001年5月2日

但是要么文本格式不正确,要么我对数学太忘了,以至于我听不懂它的含义。我不知道{1k+1}等是什么意思。但是,我的直觉告诉我这是一个序列,可以用一些数学函数来表示,或者至少可以简化,这样我就不必计算高达N的欧拉Totient值,我认为这将是很多快点。有人可以提供更好的解决方案来计算最多N的欧拉Totient函数值之和吗?

2 个答案:

答案 0 :(得分:0)

如果您可以计算给定数字 n 的因式分解,则可以很容易地找到Euler的Totient函数的值。因此,我们假设:

n = p1^k1 * p2^k2 * ... * pn^kn

然后:

H = n * (1 - 1/p1) * (1 - 1/p2) * .... * (1 - 1/pn)

例如:

n = 24 = 2 * 2 * 2 * 3
H = 24 * (1 - 1/2) * (1 - 1/3) = 24 * 1/2 * 2/3 = 24 * 1/3 = 8

在实现中可能有些棘手的是在计算中使用分数而不是十进制数。否则,您可能不会收到整数作为最终结果。

更多信息,包括上面公式背后的原因,可以在here中找到。

答案 1 :(得分:0)

在OEIS中,A002088被宣称为A005728减1(“ Wolfdieter Lang,2016年11月22日”)。对于A005728,有一些公式(“ David W. Wilson,2002年5月25日”): // shows the users of the chat channel const messageId = functions.database.ref( "/ChatMessages/{channelType}/{channelId}/{messageId}" ); // HANDLE NEW NOTIFICATION export const notificationCreatedEvent = messageId.onCreate((snapshot: any, event: any) => { // channelType is for if it is a public or private chat- if it is public it will list the mountain const { channelId } = event.params; const messageData = snapshot.val(); const message = messageData.text; const trimmedMessage = truncate(message, 20, true); // notification channel const notificationRef = admin .database() .ref(`/Notifications/${channelId}`); const notificationBody = (message.slice(0, 12) === "https://fire") ? "new image message" : trimmedMessage const payloadPrivateUser = { notification: { title: "Private Message", body: "Message: "+notificationBody } } const payload = { notification: { title: "Message in channel "+ channelId, body: "Message: " + notificationBody } } notificationRef .once("value") .then(async userListSnapshot => { const userList = await (<any>Object).values(userListSnapshot.val()); const response = channelId.length > 50 ? await admin.messaging().sendToDevice(userList, payloadPrivateUser): await admin.messaging().sendToDevice(userList, payload); }).catch(err=> { console.log(err) }) });

这个公式似乎很快。 一个未经优化的Python程序会在大约10秒钟内计算出前10000个数字。

a(n) = n(n+3)/2 - Sum(k = 2 to n, a([n/k]))

顺便说一句,请注意,要计算totient函数,不需要小数,一切都可以用整数算术完成:

num = 10000
a = [1] + [0] * num
for n in range(1, num+1):
    a[n] = n * (n+3) // 2
    for k in range(2, n+1):
        a[n] -= a[n // k]
print(a)

PS:我也不理解Labos Elemer的讲话。这让我想到了尚待证实的孪生素数猜想。无论如何,它不会给人以快速公式的印象。