计蒜客 30999 - Sum - [找规律+线性筛][2018ICPC南京网络预赛J题]

题目链接:https://nanti.jisuanke.com/t/30999

样例输入
2
5
8

样例输出
8
14

题意:

squarefree数是指不含有完全平方数( 1 除外)因子的数,

现在一个数字 $n$,可以表示成两个squarefree数 $a,b$ 相乘,即 $n = ab$,

假设 $f\left( n \right)$ 代表了 $n$ 分解成不同的数对 $\left( {a,b} \right)$ 的个数,

现在给你一个 $n$,要求 $f\left( 1 \right) + f\left( 2 \right) + \cdots + f\left( n \right)$。

题解:

不难发现,若 $n$ 含有一个因子是立方数乃至更高次方数,则此时 $f\left( n \right) = 0$,例如 $f\left( {2^3 \times 3} \right) = 0,f\left( {3^4 } \right) = 0$;

则剩下来的数,因子最多就是平方数,不妨举些例子来看每个因子能提供多少贡献:

最开始是 $f\left( 1 \right) = 1$,因为只有 $1 = 1 \times 1$,然后我们给它乘上一些因子……

  1、乘上指数为 $1$ 的因子,例如 $f\left( {1 \times 2} \right)$,加进来的 $2$ ,可以添加在原来$1 \times 1$的乘号左边($2 \times 1$),也可以添加在右边($1 \times 2$),所以贡献了“$\times 2$”,即 $f\left( {1 \times 2} \right) = f\left( 1 \right) \times 2$;

  2、乘上指数为 $2$ 的因子,例如 $f\left( {1 \times 2^2 } \right)$,加进来的 $2^2$,它不能全部添加在某一边,只能拆开来,一半添加在乘号左边,一半添加在乘号右边,即$2 \times 2$,所以贡献了“$\times 1$”,即 $f\left( {1 \times 2^2} \right) = f\left( 1 \right) \times 1$。

那么依次类推,再在后面乘上一些因子,同样的道理,指数为 $1$ 则贡献为“$\times 2$”,指数为 $2$ 则贡献为“$\times 1$”。

很容易的就能得到递推规律:假设 $n$ 的最小素因子是 $p$,则有 $n = m \times p^x$,我们分两种情况讨论:

  1、$x = 1$,$p$ 的贡献为“$\times 2$”,就有 $f\left( n \right) = f\left( m \right) \times 2$;

  2、$x = 2$,$p$ 的贡献为“$\times 1$”,就有 $f\left( n \right) = f\left( m \right)$;

那么,现在的关键就是求得 $1$ 到 $2 \times 10^7$ 的每个数字的最小素因子,线性筛素数的时候可以顺带求出。

AC代码:

#include<bits/stdc++.h>
using namespace std;

const int maxn=2e7+5;
const int MAX=2e7;

int n;
int mpf[maxn]; //存储最小素因子

/************************** 线性筛 - st **************************/
int prime[maxn];
int isPrime[maxn];
void Screen() //欧拉筛法求素数
{
    register int cnt=0;
    memset(isPrime,1,sizeof(isPrime));
    isPrime[0]=isPrime[1]=0;
    for(int i=2;i<=MAX;i++)
    {
        if(isPrime[i]) prime[cnt++]=i, mpf[i]=i;
        for(int j=0;j<cnt;j++)
        {
            if(i*prime[j]>MAX) break;
            isPrime[i*prime[j]]=0, mpf[i*prime[j]]=prime[j];
            if(i%prime[j]==0) break;
        }
    }
}
/************************** 线性筛 - ed **************************/

long long f[maxn];

int main()
{
    Screen();

    f[1]=1;
    for(int i=2;i<=MAX;i++)
    {
        int mm = mpf[i];
        if((long long)mm*mm < MAX && (long long)mm*mm*mm < MAX && i%(mm*mm*mm) == 0) f[i]=0;
        else if((long long)mm*mm < MAX && i%(mm*mm) == 0) f[i]=f[i/mm/mm];
        else f[i]=2*f[i/mm];
    }
    for(int i=2;i<=MAX;i++) f[i]+=f[i-1];

    int T;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d",&n);
        printf("%lld\n",f[n]);
    }
}

原文地址:https://www.cnblogs.com/dilthey/p/9580641.html

时间: 2024-08-30 04:48:15

计蒜客 30999 - Sum - [找规律+线性筛][2018ICPC南京网络预赛J题]的相关文章

计蒜客 31001 - Magical Girl Haze - [最短路][2018ICPC南京网络预赛L题]

题目链接:https://nanti.jisuanke.com/t/31001 题意: 一带权有向图,有 n 个节点编号1~n,m条有向边,现在一人从节点 1 出发,他有最多 k 次机会施展魔法使得某一条边的权变成 0,问他走到节点 n 的最小权值为多少. 题解: 将dist数组和vis数组都扩展一维: dist[c][i]代表:已经使用了 c 次变0魔法后,走到节点 i 的最短距离: vis[c][i]代表:已经使用了 c 次变0魔法后,走到节点 i 的最短距离,这个最短距离是否已经被准确计算

计蒜客 30990 - An Olympian Math Problem - [简单数学题][2018ICPC南京网络预赛A题]

题目链接:https://nanti.jisuanke.com/t/30990 Alice, a student of grade 6, is thinking about an Olympian Math problem, but she feels so despair that she cries. And her classmate, Bob, has no idea about the problem. Thus he wants you to help him. The proble

2018计蒜客复赛 贝壳找房函数最值(贪心+优先队列)

贝壳找房函数最值 35.12% 1000ms 262144K 贝壳找房的攻城狮最近在研究一次函数 f(x) = ax + bf(x)=ax+b. 现在有 nn 个一次函数,f_i(x) = a_ix+b_i,\ i = \{1 \mathellipsis n\}fi?(x)=ai?x+bi?, i={1…n}. 容易发现,一次函数嵌套一次函数,还是一次函数. \displaystyle f_{i}(f_{j}(x)) = a_{i} ( a_{j}x + b_{j}) + b_{i}fi?(fj

【找规律】计蒜客17118 2017 ACM-ICPC 亚洲区(西安赛区)网络赛 E. Maximum Flow

题意:一张有n个点的图,结点被编号为0~n-1,i往所有编号比它大的点j连边,权值为i xor j.给你n,问你最大流. 打个表,别忘了把相邻两项的差打出来,你会发现神奇的规律……你会发现每个答案都是由某些特定的数加起来组成的,最好把它们也打出来. #include<cstdio> using namespace std; typedef long long ll; #define MOD 1000000007ll ll n; int main(){ // freopen("e.ou

【推导】计蒜客17116 2017 ACM-ICPC 亚洲区(西安赛区)网络赛 C. Sum

题意:S(x)被定义为x的十进制表示下的数位之和.给你x,让你找一个正整数k,使得S(kx)能被233整除.k不超过2千位. 由于x不超过1000000,不论x是多少,10000000重复233次一定是合法的. #include<cstdio> using namespace std; int T,x; int main(){ scanf("%d",&T); for(;T;--T){ scanf("%d",&x); for(int i=1

计蒜客 31452 - Supreme Number - [简单数学][2018ICPC沈阳网络预赛K题]

题目链接:https://nanti.jisuanke.com/t/31452 A prime number (or a prime) is a natural number greater than $1$ that cannot be formed by multiplying two smaller natural numbers. Now lets define a number $N$ as the supreme number if and only if each number m

【推导】计蒜客17119 2017 ACM-ICPC 亚洲区(西安赛区)网络赛 F. Trig Function

题意:给你n,m,让你求cos(nx)的展开式的(cos(x))^m项的系数. 更一般的式子是这样的:. 队友的代码: #include<cstdio> #include<algorithm> #include<queue> #include<set> using namespace std; long long n,k,i,ans; long long mo=998244353; long long ni(long long a,long long b)

【分块】计蒜客17120 2017 ACM-ICPC 亚洲区(西安赛区)网络赛 G. Xor

题意:给一棵树,每个点有权值.q次询问a,b,k,问你从a点到b点,每次跳距离k,权值的异或和? 预处理每个点往其根节点的路径上隔1~sqrt(n)的距离的异或和,然后把询问拆成a->lca(a,b),lca(a,b)->b,讨论一下即可,细节比较多. 队友的代码: #include <cmath> #include <cstdio> #include <cstring> #include <iostream> #include <algo

【二项式定理】【推导】计蒜客17115 2017 ACM-ICPC 亚洲区(西安赛区)网络赛 B. Coin

题意:投一枚硬币向上的概率是q/p.问你投K枚硬币,向上的枚数为偶数枚的概率是? 要求的即为. 这个东西是个二项展开式的偶数项系数和,来,我们复习一下高中数学,设f(x)=(ax+b)^n,则其偶数项系数和为(f(1)+f(-1))/2. #include<cstdio> using namespace std; typedef long long ll; #define MOD 1000000007ll int T; ll p,q,K; ll Quick_Pow(ll a,ll p,ll m