使用K颜色的不同项链数量 我有一个任务,用C++中的K颜色找到不同项链的数量。

使用K颜色的不同项链数量 我有一个任务,用C++中的K颜色找到不同项链的数量。,c++,algorithm,math,combinatorics,C++,Algorithm,Math,Combinatorics,如果其中一条项链 无法通过旋转第二条项链从第二条项链获得 任何角度的项链。 求不同项链的总数(10^9+7) 我认为这个公式很好地解决了一个问题: 我用C++实现了一个程序: #include <algorithm> #include <iostream> #include <cmath> using namespace std; const int M = 1e9 + 7; int main() { long long n, k; ci

如果其中一条项链 无法通过旋转第二条项链从第二条项链获得 任何角度的项链。 求不同项链的总数(10^9+7)

我认为这个公式很好地解决了一个问题:

我用C++实现了一个程序:

#include <algorithm>
#include <iostream>
#include <cmath>
using namespace std;
const int M = 1e9 + 7;

int main()
{
    long long  n, k;
    cin >> n >> k;

    long long x = 0;
    for (int i = 0; i < n; ++i) {
        x += pow(k, __gcd(i,n));
    }

    cout << (int)(((double)1/n) * x) % M;
    return 0;
}
#包括
#包括
#包括
使用名称空间std;
常数int M=1e9+7;
int main()
{
长n,k;
cin>>n>>k;
长x=0;
对于(int i=0;icout对不起,如果您的公式不正确,我们无能为力,但这是您的公式的正确实现方式

在您的代码中,循环变量
i
与公式不同。您正在移动
i=0,…,n-1
,但公式显示
i=1,2,….n

更新:我认为你的行
x+=pow(k,u gcd(I,n));
不太正确。当
x+pow(k,u gcd(I,n))
将大于10^9+7时,你应该取模,但你没有这样做

为了让代码更清楚,
模运算是分布在
+
上的,因此您可以编写

    ( a + b ) % c = ( ( a % c ) + ( b % c ) ) % c
但是,
不是分布在
/
上的,所以不能只写

   ( a / b ) % c = ( ( a % c ) / ( b % c ) ) % c
要计算
(x/y)%M
,您必须计算

    (x * MMI(y)) % M
感谢@ivlad指出MMI缺陷:)

改变

 for (int i = 0; i < n; ++i) {
    x += pow(k, __gcd(i,n));
 }
 cout << (int)(((double)1/n) * x) % M;
for(int i=0;iMOD)x%=MOD;
}
y=(y*y);
如果(y>MOD)y%=MOD;
b/=2;
}
返回x;
}
长-长修改(长n,长m){
返回功率(n,m-2,m);
}
int main()
{
长n,k;
cin>>n>>k;

对于(长i=1;i考虑数字限制

long-long
可以是
unsigned long-long
甚至
long-double

double
可以是
长double
。这实际上取决于平台,但可能是原因


顺便说一句,
n
被定义为
long
,它真的会那么大吗?如果是的话,你的循环将花费很长时间,你可能会“超过时间限制”。如果没有,只需声明它
int
。声明它
long
int
就足够了,可能会导致一些错误!!

我发现您的程序有两个问题。第一个问题是
pow
即使是
k
n
的小值也会溢出。这取决于输入的大小(你没有给出),
pow
甚至在你取模之前就可能溢出。你应该用你自己的
powModM
替换
pow
,它更频繁地取
%M
。比如

int powModM(int k, int n, int M) {
  int res = 1;
  for (int i = 0; i < n; ++i) {
    res = (res * k) % M;
  }
  return res;
}

实际上,你的公式是不正确的。正确的公式可以在这里找到:


我的实现刚刚完成。

检查循环条件。与公式中的条件不匹配。您好!抱歉,没有更改:(
++i
不会做您认为它会做的事情。具体来说,for循环条件总是先计算初始值,然后计算终止值,然后计算递增值。因此,无论您是在for循环中编写
++i
还是
i++
,都无关紧要。但由于
++i
可能会误导人们认为循环正在做其他事情始终建议使用
i++
作为正在发生的事情的自我记录提醒。当前的所有答案很可能都是错误的,因为
x
在for循环后可能会超过偶数
long
,即使
n
小到
63
k
小到
2
。模为t这里有一个原因:你必须在每一步计算它。@ SyBeMeN-UH,相反的是。在C++中总是使用<代码> ++i < /> >而不是<代码> i++< /> >。原因是后者有时比前者慢——不是内置的类型,如代码> int <代码>,而是自定义类型。无论如何,它们的语义在这里是相同的。我看不出有什么会让人困惑……嗨!谢谢,我在代码中修复了它,但没有任何改变!解决方案再次通过了一半的测试用例。哦,我有一个错误
file.cc:18:49:error:binary expression的操作数无效('typename enable_if::type'(aka'double')x=((x%M)+(pow(k,u gcd(I,n)%M))%M;
。我在这里删除了最后一个
%M
,但通过了一半的测试用例。这是错误的:取模后不能除以
n
,然后再取模。它会给出错误的答案。@IVlad我不知道你计算了
x
M
。然后你将结果除以
n
。这就是wrong.即使
n
很小,求幂运算也会导致整个东西溢出。我不理解逆。什么是参数
a
m
a
是你的
n
m
是你的
m
int powModM(int k, int n, int M) {
  int res = 1;
  for (int i = 0; i < n; ++i) {
    res = (res * k) % M;
  }
  return res;
}
public static long inverse(long a, long m) { // mult. inverse of a mod m
    long r = m;
    long nr = a;
    long t = 0;
    long nt = 1;
    long tmp;
    while (nr != 0) {
      long q = r/nr;
      tmp = nt; nt = t - q*nt; t = tmp;
      tmp = nr; nr = r - q*nr; r = tmp;
    }
    if (r > 1) return -1; // no inverse
    if (t < 0) t += m;
    return t;
  }