【JZOJ4755】【NOIP2016提高A组模拟9.4】快速荷叶叶变换
2024-10-08 02:08:24
题目描述
输入
一行,包含两个整数N,M。
输出
1个整数,FHT(N,M) mod 1000000007的值。
样例输入
3 4
样例输出
1
数据范围
对于 40% 的数据,1 ≤ N,M ≤ 1000
对于 60% 的数据,1 ≤ N,M ≤ 10^6
对于 100% 的数据,1 ≤ N,M ≤ 10^9
解法
答案=ans(n)*ans(m) (其中ans(n)=sigma(n%i));
那么现在只用考虑ans(n)怎么求。
ans(n)=sigma(n mod i)
=sigma(n-i*(n div i))
=n^2-sigma(i)*sigma(n div i)
由于sigma(n div i)最多只有n^0.5种取值。所以可以分段计算。
证明:
令i=1..n^0.5,那么对应的n div i区间就在[n^0.5,n],所以约数最多有2*n^0.5个。
代码
#include<iostream>
#include<stdio.h>
#include<math.h>
#include<string.h>
#include<algorithm>
#define ll long long
#define sqr(x) ((x)*(x))
#define ln(x,y) int(log(x)/log(y))
using namespace std;
const char* fin="aP1.in";
const char* fout="aP1.out";
const int inf=0x7fffffff;
const int mo=1000000007;
int read(){
int x=0;
char ch=getchar();
while (ch<'0' || ch>'9') ch=getchar();
while (ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar();
return x;
}
int n,m,i,j,k;
ll ans,tmp;
ll work(int a,int b){
ll i,j=1,k=0,num,tmp,st=a;
while (a){
num=(a-b)/(j+1)+((a-b)%(j+1)?1:0);
if (num<=100) {
break;
}
tmp=b+num*j-j;
k=(k+(b+tmp)*num/2)%mo;
a-=num;
b=(tmp+j)%a;
j++;
}
for (;a;a--) k=(k+(st%a))%mo;
return k;
}
int main(){
scanf("%d%d",&n,&m);
ans=(work(n,0)*work(m,0))%mo;
printf("%lld",ans);
return 0;
}
启发
n%i=n-n div i*i。
当i=1..n时,n div i最多有n^0.5个取值,所以可以分段计算。
最新文章
- sql之多表连接
- Word论文写作如何实现公式居中、编号右对齐
- 字符串与模式匹配(一)&mdash;&mdash;KMP算法
- jQuery--捕获键盘敲击
- CentOS 7 内核更新后删除旧内核
- [原创]java WEB学习笔记49:文件上传基础,基于表单的文件上传,使用fileuoload 组件
- Mac下Tomcat启动时乱码
- UNIX/Linux网络编程基础:图解TCP/IP协议栈
- The Socket API, Part 3: Concurrent Servers
- 【转+心得】WinDbg+VM9双机调试无法连接解决方案
- openssl 非对称加密算法DSA命令详解
- Android 打包签名 从生成keystore到完成签名
- linux-0.11抠代码-GDB+VMWARE
- IE10去掉input的type=”text”输入内容时出现的小叉号(X)和type=”password”出现的小眼睛图标
- 元类(meta class)
- React Native组件、生命周期及属性传值props详解
- VUE滚动条插件——vue-happy-scroll
- AngularJs 文件上传(实现Multipart/form-data 文件的上传)
- 二 Hive分桶
- Linux信号函数