2019 Multi-University Training Contest 1 - 1011 - Function - 数论
http://acm.hdu.edu.cn/showproblem.php?pid=6588
新学到了一个求n以内与m的gcd的和的快速求法。也就是下面的S1。
①求:
$ \sum\limits_{i=1}^{n}gcd(m,i) $
②枚举d:
$ \sum\limits_{d|m} d \sum\limits_{i=1}^{n} [gcd(m,i)==d] $
③显然:
$ \sum\limits_{d|m} d \sum\limits_{i=1}^{\lfloor\frac{n}{d}\rfloor} [gcd(\frac{m}{d},i)==1] $
到这一步已经可以递归求了,琪琪说是 \(O(n^{\frac{3}{4}})\) ,不过题解可以继续往下。
④为了方便直接考虑 $ \sum\limits_{i=1}^{n} [gcd(m,i)==1] $ ,反演(大概):
$ \sum\limits_{i=1}^{n} \sum\limits_{d|gcd(m,i)} \mu(d) $
⑤交换一下顺序,枚举d,很显然n以内的d的倍数都会贡献一个mu(d):
$ \sum\limits_{d|m} \mu(d) \lfloor\frac{n}{d}\rfloor $
下面的是根据题解的实现,不过是__int64的版本。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef __int64 lll;
const int mod = 998244353;
const int MAXN = 10000000;
int phi[MAXN + 1];
int pri[MAXN + 1], pritop;
bool notpri[MAXN + 1];
void sieve() {
int n = MAXN;
pri[1] = phi[1] = 1;
for(int i = 2; i <= n; i++) {
if(!pri[i])
pri[++pritop] = i, phi[i] = i - 1;
for(int j = 1, tmp; j <= pritop && (tmp = i * pri[j]) <= n; j++) {
pri[tmp] = 1;
if(i % pri[j])
phi[tmp] = phi[i] * phi[pri[j]];
else {
phi[tmp] = phi[i] * pri[j];
break;
}
}
}
}
ll S1(lll n, int m) {
//sigma gcd(i,m) [1,n]
ll res = 0;
for(int T = 1; T * T <= m; ++T) {
if(!(m % T)) {
res += (n / T) * phi[T];
if(T * T != m) {
res += (n / (m / T)) * phi[(m / T)];
}
}
}
res %= mod;
return res;
}
ll qpow(ll x, int n) {
ll res = 1;
while(n) {
if(n & 1)
res = res * x % mod;
x = x * x % mod;
n >>= 1;
}
return res;
}
const int inv2 = qpow(2ll, mod - 2);
const int inv6 = qpow(6ll, mod - 2);
ll sigma1(ll x) {
return x * (x + 1ll) % mod * inv2 % mod;
}
ll sigma2(ll x) {
return x * (x + 1ll) % mod * (2ll * x + 1ll) % mod * inv6 % mod;
}
ll S2_1(int r, int T) {
int c = r / T;
ll res = 0;
res += 3ll * T * sigma2(c);
res += 3ll * sigma1(c);
res += c;
res %= mod;
return res;
}
ll S2(int r) {
ll res = 0;
for(int T = 1; T <= r; ++T) {
res += 1ll * phi[T] * S2_1(r, T) % mod;
}
res %= mod;
return res;
}
ll S0(lll n) {
lll i, i3;
for(i = 1;; ++i) {
lll tmp = i * i * i;
if(tmp > n) {
--i;
break;
} else
i3 = tmp;
}
ll res = 0;
res += S1(n, i) - S1(i3 - 1, i);
res += S2(i - 1);
res = (res % mod + mod) % mod;
return res;
}
inline lll read() {
lll x = 0;
char c;
do {
c = getchar();
} while(c < '0' || c > '9');
do {
x = (x << 3) + (x << 1) + c - '0';
c = getchar();
} while(c >= '0' && c <= '9');
return x;
}
int main() {
#ifdef Yinku
freopen("Yinku.in", "r", stdin);
#endif // Yinku
sieve();
int T;
cin >> T;
lll n;
while(T--) {
n = read();
cout << S0(n) << endl;
}
}
其实具体的思路还是要先分成两部分来算,但是我当时不会计算这个S1导致T了。其实计算S2的时候在整数较大的时候发生了溢出。也就是c*c的位置。所以说以后非数组的值一律开ll就对了。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef __int128 lll;
const int mod = 998244353;
const int MAXN = 10000000;
int pk[MAXN + 1];
int sum1[MAXN + 1];
int phi[MAXN + 1];
int pri[MAXN + 1], pritop;
bool notpri[MAXN + 1];
void sieve() {
int n = MAXN;
pri[1] = pk[1] = sum1[1] = phi[1] = 1;
for(int i = 2; i <= n; i++) {
if(!pri[i])
pri[++pritop] = i, phi[i] = i - 1, pk[i] = i, sum1[i] = 2 * i - 1;
for(int j = 1, p, tmp; j <= pritop && (p = pri[j]) && (tmp = i * p) <= n; j++) {
pri[tmp] = 1;
if(i % p) {
pk[tmp] = pk[p];
sum1[tmp] = 1ll * sum1[i] * sum1[p] % mod;
phi[tmp] = phi[i] * phi[p];
} else {
pk[tmp] = pk[i] * p;
if(pk[tmp] == tmp) {
sum1[tmp] = (1ll * sum1[i] * p % mod + (tmp - tmp / p)) % mod;
} else {
sum1[tmp] = 1ll * sum1[pk[tmp]] * sum1[tmp / pk[tmp]] % mod;
}
phi[tmp] = phi[i] * p;
break;
}
}
}
}
int sum2[MAXN + 1];
ll qpow(ll x, int n) {
ll res = 1;
while(n) {
if(n & 1)
res = res * x % mod;
x = x * x % mod;
n >>= 1;
}
return res;
}
void init() {
for(int c = 1, c1 = 2, c2 = 7, f1 = 1; c <= MAXN;) {
sum2[c] = ((1ll * c2 - f1 + mod) % mod * sum1[c] % mod * qpow(c, mod - 2) % mod + c + sum2[c - 1]) % mod;
++c, ++c1, f1 = c2 + 1;
c2 = (1ll * c1 * c1 % mod * c1 % mod - 1 + mod) % mod;
}
}
ll S1(lll n, int m) {
//sigma gcd(i,m) [1,n]
ll res = 0;
for(int T = 1; T * T <= m; ++T) {
if(!(m % T)) {
res += (n / T) * phi[T];
if(T * T != m) {
res += (n / (m / T)) * phi[(m / T)];
}
}
}
res %= mod;
return res;
}
ll S0(lll n) {
lll i, i3;
for(i = 1;; ++i) {
lll tmp = i * i * i;
if(tmp > n) {
--i;
break;
} else
i3 = tmp;
}
ll res = 0;
res += S1(n, i) - S1(i3 - 1, i);
res += sum2[i - 1];
res = (res % mod + mod) % mod;
return res;
}
inline lll read() {
lll x = 0;
char c;
do {
c = getchar();
} while(c < '0' || c > '9');
do {
x = (x << 3) + (x << 1) + c - '0';
c = getchar();
} while(c >= '0' && c <= '9');
return x;
}
int main() {
#ifdef Yinku
freopen("Yinku.in", "r", stdin);
#endif // Yinku
sieve();
init();
int T;
cin >> T;
lll n;
while(T--) {
n = read();
cout << S0(n) << endl;
}
}
2019 Multi-University Training Contest 1 - 1011 - Function - 数论的更多相关文章
- 2014 Multi-University Training Contest 1/HDU4861_Couple doubi(数论/法)
解题报告 两人轮流取球,大的人赢,,, 贴官方题解,,,反正我看不懂.,,先留着理解 关于费马小定理 关于原根 找规律找到的,,,sad,,, 非常easy找到循环节为p-1,每个循环节中有一个非零的 ...
- 2019 Multi-University Training Contest 2 - 1011 - Keen On Everything But Triangle - 线段树
http://acm.hdu.edu.cn/showproblem.php?pid=6601 首先要贪心地想,题目要最长的边长,那么要怎么构造呢?在一段连续的区间里面,一定是拿出最长的三根出来比,这样 ...
- 2016 Multi-University Training Contest 5 1011 Two DP
http://acm.hdu.edu.cn/showproblem.php?pid=5791 HDU5791 Two 题意 :两个数组,多少个不连续子串相等 思路: dp[i][j] :a串i结尾,b ...
- HDU 6342.Problem K. Expression in Memories-模拟-巴科斯范式填充 (2018 Multi-University Training Contest 4 1011)
6342.Problem K. Expression in Memories 这个题就是把?变成其他的使得多项式成立并且没有前导零 官方题解: 没意思,好想咸鱼,直接贴一篇别人的博客,写的很好,比我的 ...
- 2016 Multi-University Training Contest 3 1011【鸽巢原理】
题解: 坐标(0,m)的话,闭区间,可能一共有多少曼哈顿距离? 2m 但是给一个n,可能存在n(n+1)/2个曼哈顿距离 所以可以用抽屉原理了 当n比抽屉的数量大,直接输出yes 不用计算 那...N ...
- 2019 Nowcoder Multi-University Training Contest 4 E Explorer
线段树分治. 把size看成时间,相当于时间 $l$ 加入这条边,时间 $r+1$ 删除这条边. 注意把左右端点的关系. #include <bits/stdc++.h> ; int X[ ...
- 2019 Nowcoder Multi-University Training Contest 1 H-XOR
由于每个元素贡献是线性的,那么等价于求每个元素出现在多少个异或和为$0$的子集内.因为是任意元素可以去异或,那么自然想到线性基.先对整个集合A求一遍线性基,设为$R$,假设$R$中元素个数为$r$,那 ...
- 2019杭电多校一 K. Function (数论)
大意: 给定$n(n\le 10^{21})$, 求$\sum\limits_{i=1}^n gcd(\lfloor\sqrt[3]{i}\rfloor,i)\mod 998244353$ 首先立方根 ...
- 2015 Multi-University Training Contest 8 hdu 5390 tree
tree Time Limit: 8000ms Memory Limit: 262144KB This problem will be judged on HDU. Original ID: 5390 ...
随机推荐
- FMC228- 四路16位1.2Gsps DA FMC子卡模块
FMC228- 四路16位1.2Gsps DA FMC子卡模块 一.概述 FMC连接器是一种高速多pin的互连器件,广泛应用于板卡对接的设备中,特别是在xilinx公司的所有开发板中 ...
- ubuntu16.04安装mysql数据库
安装 sudo apt-get install mysql-server(安装过程中按提示设置root密码) sudo apt-get install mysql-client sudo apt-ge ...
- 转载:CentOS yum 源的配置与使用
转载自:http://www.cnblogs.com/mchina/archive/2013/01/04/2842275.html 一.yum 简介 yum,是Yellow dog Updater, ...
- prufer 序列 学习笔记
prufer 序列是一种无根树的序列,对于一个 \(n\) 个点的树,其 prufer 序列的长度为 \(n-2\). prufer 序列和原树之间都可以唯一地相互转化. 构造 构造 prufer 序 ...
- File类常用方法和枚举
新建一个file对象: File f = new File("F:\\01.JAVA基础300集\\05_常用类\\122.File类的使用.mp4"); (文件路径也可以用&qu ...
- 快速开发框架下载地址(github)
eladmin:https://github.com/elunez/eladmin bootDo:https://www.oschina.net/p/bootdo
- macaca搭建
对于新鲜的事务总是那么好奇,在自动化的过程中,有幸了解到macaca,记录下安装过程,具体介绍请移步官网:https://github.com/macacajs/ python版本参考:https:/ ...
- 029:url标签使用详解
url标签使用详解: 在模版中,我们经常要写一些 url ,比如某个 a 标签中需要定义 href 属性.当然如果通过硬编码的方式直接将这个 url 写死在里面也是可以的.但是这样对于以后项目维护可能 ...
- 3 Base64编码主要应用在那些场合?
,电子邮件数据也好,经常要用到Base64编码,那么为什么要作一下这样的编码呢? 我们知道在计算机中任何数据都是按ascii码存储的,而ascii码的128-255之间的值是不可见字符.而在网络上交换 ...
- java匿名内部类 (转载)
匿名内部类也就是没有名字的内部类 正因为没有名字,所以匿名内部类只能使用一次,它通常用来简化代码编写 但使用匿名内部类还有个前提条件:必须继承一个父类或实现一个接口 实例1:不使用匿名内部类来实现抽象 ...