您的位置:首页 > 其它

数论(CRB and Candies,HDU 5407)

2017-07-22 21:26 232 查看
题目链接:https://vjudge.net/problem/HDU-5407

暴力打了个表,感觉找不到什么规律。

1

2

3

12

10

60

105

280

252

2520

2310

27720

25740

24024

45045

720720

想把整个表全部打完估计要一整天。

然后规律是g[i]=lcm(1,2,...,i,i+1)/(i+1)。

然后有公式lcm(1,2,...,n)=(n==p^k)?lcm(1,2,...,n-1)*p:lcm(1,2,...,n-1)

我感觉还是挺难找到规律的吧。。

具体数论上的公式就是

b
=lcm(1,2,...,n)=(n==p^k)?b[n-1]*p:b[n-1]

a
=lcm(C(n,0),C(n,1),...,C(n,n))=b[n+1]/(n+1)

p是某个质数。

参考博客:

http://www.cnblogs.com/liyinggang/p/5578654.html

http://www.cnblogs.com/aoxuets/p/4746278.html

也看到有人通过思考找到了简单的规律

http://www.cnblogs.com/crazyacking/p/4748294.html

具体思路就是考虑求lcm(C(n,0),C(n,1),...,C(n,n))

可以考虑对每一项唯一分解,然后维护每个质数的最高次数,最后乘起来就是答案。

数与数之间的联系还是挺强的。

毕竟有公式C(n,k)=C(n,k-1)*(n-k+1)/k

而且组合数是对称的,所以其实只用求一半。

暴力做肯定是要超时的,毕竟一次回答需要O(n^2)

可以考虑从这个规律入手,找到一些简便的算法。

对于当前项C(n,k),我们比之前新引入了一个因子(n-k+1),同时也删除了一个因子k。

好吧,其实我不太明白。

最后还有数列网

http://oeis.org/

一查就知道了。

跟别人的差距很大

两份代码

#include<stdio.h>
#include<vector>
#include<math.h>
using namespace std;
typedef long long ll;
const int maxn = 1000010;
const int mod = 1e9+7;

vector<int>pri;
int vis[maxn];

void getpri()
{
int m = sqrt(maxn+0.5);
for(int i=2;i<=m;i++) if(!vis[i])
for(int j=i*i;j<maxn;j+=i) vis[j]=1;
for(int i=2;i<maxn;i++) if(!vis[i])
pri.push_back(i);

}

void solve()
{
int n;
scanf("%d",&n);
int ans=1;
for(int i=0;i<(int)pri.size();i++)
for(ll j=pri[i];j<=n;j*=pri[i])
if((n+1)%j!=0)
ans=1ll*ans*pri[i]%mod;
printf("%d\n",ans);
}

int main()
{
getpri();
int T;
scanf("%d",&T);
while(T--) solve();
return 0;
}

#include<stdio.h>
#include<vector>
#include<math.h>
using namespace std;
typedef long long ll;
const int maxn = 1000010;
const int mod = 1e9+7;

vector<int>pri;
int vis[maxn];
int mul[maxn];
int f[maxn];
int g[maxn];
int inv[maxn];

int mp(int x,int n)
{
int ret=1;
while(n)
{
if(n&1) ret=1ll*ret*x%mod;
x=1ll*x*x%mod;
n>>=1;
}
return ret;
}

void getpri()
{
for(int i=0;i<maxn;i++)
inv[i]=mp(i,mod-2);
int m = sqrt(maxn+0.5);
for(int i=2;i<=m;i++) if(!vis[i])
for(int j=i*i;j<maxn;j+=i) vis[j]=1;
for(int i=2;i<maxn;i++) if(!vis[i])
pri.push_back(i);
for(int i=0;i<maxn;i++) mul[i]=1;
for(int i=0;i<(int)pri.size();i++)
for(ll j=pri[i];j<maxn;j*=pri[i])
mul[j]=pri[i];
f[1]=1;
for(int i=2;i<maxn;i++)
{
f[i]=1ll*f[i-1]*mul[i]%mod;
g[i-1]=1ll*f[i]*inv[i]%mod;
}
}

void solve()
{
int n;
scanf("%d",&n);
printf("%d\n",g
);
}

int main()
{
getpri();
int T;
scanf("%d",&T);
while(T--) solve();
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: