[BZOJ 2154] Crash的数字表格
2015-06-18 20:48
405 查看
2154: Crash的数字表格
Time Limit: 20 Sec Memory Limit: 259 MBSubmit: 1337 Solved: 531
[Submit][Status][Discuss]
Description
今天的数学课上,Crash小朋友学习了最小公倍数(Least Common Multiple)。对于两个正整数a和b,LCM(a, b)表示能同时被a和b整除的最小正整数。例如,LCM(6, 8) = 24。回到家后,Crash还在想着课上学的东西,为了研究最小公倍数,他画了一张N*M的表格。每个格子里写了一个数字,其中第i行第j列的那个格子里写着数为LCM(i, j)。一个4*5的表格如下: 1 2 3 4 5 2 2 6 4 10 3 6 3 12 15 4 4 12 4 20 看着这个表格,Crash想到了很多可以思考的问题。不过他最想解决的问题却是一个十分简单的问题:这个表格中所有数的和是多少。当N和M很大时,Crash就束手无策了,因此他找到了聪明的你用程序帮他解决这个问题。由于最终结果可能会很大,Crash只想知道表格里所有数的和mod 20101009的值。Input
输入的第一行包含两个正整数,分别表示N和M。Output
输出一个正整数,表示表格中所有数的和mod 20101009的值。Sample Input
4 5Sample Output
122【数据规模和约定】
100%的数据满足N, M ≤ 107。
HINT
Source
数论【题解】
用莫比乌斯繁衍(题解均省略取模运算)
设sum2(i)=i*(i+1)/2
设函数sum(i,j)=sum2(i)*sum2(j)
那么,ans=sigma (D=1 to min(n,m)) sum(n/d,m/d)* (sigma (i|D) Di*mu[i])
(这是可以推出来的)
然后呢,YSY聚聚告诉我了一个方法:
线性筛筛素数,记录i最小素数因子为mz[i]
然后,设f[D] 为 (sigma (i|D) Di*mu[i]),那么,
f[D]=f[D/mz[i]](mz[i/mz[i]]==mz[i])
f[D]=f[D/mz[i]]*(1-mz[i]) (else)
那么,即可在O(n)时间内处理
可以用前缀和维护f,则在O(sqrt n)之内处理完
需要强调的是!!!!!!!
括号啊括号!!long long啊long long!!!
WA了10几次,精度爆炸了
首先是sum,不能连乘3次!!
long long 强制转换要放内部!
唉,ysy一遍A,我WA了10几次,TAT
#include<bits/stdc++.h> using namespace std; int prime[1000010]; int tot,mz[10000010]; int f[10000010],n,m; long long ans; const int mod=20101009; long long sum(int ki,int kj) { return ((((long long)ki*(ki+1)/2)%mod)*(((long long)kj*(kj+1)/2)%mod))%mod; } int main() { //freopen("a.out","w",stdout); scanf("%d%d",&n,&m); if (n>m) { int t=n; n=m; m=t; } for (int i=2;i<=n;++i) { if (!mz[i]) { prime[++tot]=i; mz[i]=i; } for (int j=1;j<=tot&&i*prime[j]<=n;++j) { mz[i*prime[j]]=prime[j]; if(i%prime[j]==0) break; } } //for (int i=1;i<=tot;++i) cout<<prime[i]<<endl; //for (int i=1;i<=n;++i) cout<<mz[i]<<endl; f[1]=1; for (int i=2;i<=n;++i) if(mz[i/mz[i]]==mz[i]) f[i]=f[i/mz[i]]; else f[i]=((long long)f[i/mz[i]]*(1-mz[i]))%mod; for (int i=2;i<=n;++i) f[i]=((long long)f[i]*i+f[i-1])%mod; int j=0; for (int i=1;i<=n;i=j+1) { j=min(n/(n/i),m/(m/i)); ans=(ans+(sum(n/i,m/i)*(long long)(f[j]-f[i-1])%mod))%mod; } printf("%lld\n",(ans+mod)%mod); return 0; }
View Code
相关文章推荐
- 黑马程序员------比较器
- 【华为oj】简单密码破解
- 黑马程序员------集合
- 特征值和特征矩阵的意义和应用
- 全局/静态变量初始化为0放在bss段还是data段
- 京东成都研究所奋战618
- OC11_自动释放池
- 吸费电话致富 加值电话合作 声讯电话平台
- Bean对象封装,数据分离
- win8下uboot启动卡制作
- 分布式版本管理git学习资料整理推荐
- 第15周上机实践项目1——用二进制文件处理学生成绩
- UVA 156 Ananagrams
- 黑马程序员——集合框架
- startActivityForResult和setResult详解
- 创世纪
- 自学Lua(1)--Lua语法特点
- 关于nginx配置的不完全总结
- OC10_数组的内存管理
- Redis命令学习-Set(集合)