[zroj 51] [Pendulum] : 线性筛

问题描述

Evan 站在巨大的世纪钟摆前,观察着钟摆上方数字的塌缩。他发现,钟摆每摆动?次,上方的数字就会变成把它分解质因数后每一项的和。例如 12 =2 × 2 × 3,那么摆动一次后数字变成 2 + 2 + 3 = 7。现在,上方的数字正好是 x。Evan 还有 y 秒就要去新世界探索了,他想知道在钟摆摆动 y 次到他离开时,上方的数字是多少。

输入格式

第一行一个整数n,表示询问个数。后面n行每行两个整数x和y。

输出格式

n行,每行一个答案表示离开时上方的数字。

样例输入

2

5 3

20 1

样例输出

5

9

数据范围

n<=3*10^5,x<=10^7,y<=10^9

一些想法

一句话题意:给定x和y,每次将x质因数分解后的每一项求和作为新的x,问y次后的x

暴力的搞一下10^7以内的所有数进行的变换,发现每个数的变换次数都不超过20次就会变成质数,而我们发现一旦变为了素数或者是4,无论再变换多少次都是不再变的。于是我们使用线性筛,开一个f数组,f[i]表示i质因数分解后的每一项的和。根据分析很明显的知道当i为素数时f[i]=i,当为一个合数为prime[j]*i时f[prime[j]*i]=f[i]+prime[j]。所以最终我们只需要在欧拉筛中插入两句话。

#include<cstdio>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<queue>
using namespace std;
#define debug(x) cerr<<#x<<‘=‘<<x<<endl
#define MAXN 10000001
#define NUM 669999

int prime[NUM];
bool flag[MAXN];
int x,y,n;
int f[MAXN];

int Euler(int n){
    int cntprime=0;
    memset(flag,false,sizeof(flag));
    memset(f,0,sizeof(f));
    for (int i = 2; i <= n; i++)
    {
        if (!flag[i]) {
            f[i]=i; //第一句
            prime[++cntprime] = i;
        }
          for (int j = 1; j <= cntprime && prime[j]*i <= n; j++)    {
            f[prime[j]*i]=f[i]+prime[j];
             flag[i*prime[j]] = true;// 第二句
             if (i % prime[j] == 0) break;
         }
    }
}

int work(int x,int y){
    while (y){
        if (x==f[x]) {//分解为素数时不会再变化
        ans=x;
        break;
        }
        else ans=x=f[x];
        y--;
    }
    return ans;
}

int main (){
    Euler(MAXN);
    cin>>n;
    for (int i=1;i<=n;i++){
        scanf("%d%d",&x,&y);
        printf("%d\n",work(x,y));
    }
    return 0;
}


九月

目击众神死亡的草原上野花一片

远在远方的风比远方更远

我的琴声呜咽 泪水全无

我把这远方的远归还草原

一个叫木头 一个叫马尾

我的琴声呜咽 泪水全无

远方只有在死亡中凝聚野花一片

明月如镜高悬草原映照千年岁月

我的琴声呜咽 泪水全无

只身打马过草原



Sylvia

二零一七年八月九日

时间: 2024-11-06 07:51:29

[zroj 51] [Pendulum] : 线性筛的相关文章

bzoj 3309 DZY Loves Math - 莫比乌斯反演 - 线性筛

对于正整数n,定义f(n)为n所含质因子的最大幂指数.例如f(1960)=f(2^3 * 5^1 * 7^2)=3, f(10007)=1, f(1)=0. 给定正整数a,b,求sigma(sigma(f(gcd(i,j)))) (i=1..a, j=1..b). Input 第一行一个数T,表示询问数. 接下来T行,每行两个数a,b,表示一个询问. Output 对于每一个询问,输出一行一个非负整数作为回答. Sample Input 4 7558588 9653114 6514903 445

* SPOJ PGCD Primes in GCD Table (需要自己推线性筛函数,好题)

题目大意: 给定n,m,求有多少组(a,b) 0<a<=n , 0<b<=m , 使得gcd(a,b)= p , p是一个素数 这里本来利用枚举一个个素数,然后利用莫比乌斯反演可以很方便得到答案,但是数据量过大,完全水不过去 题目分析过程(从别人地方抄来的) ans = sigma(p, sigma(d, μ(d) * (n/pd) * (m/pd))) Let s = pd, then ans = sigma(s, sigma(p, μ(s/p) * (n/s) * (m/s))

[BZOJ2818] Gcd (数论,欧拉函数,线性筛)

题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2818 必须用线性筛. 1 #include <bits/stdc++.h> 2 using namespace std; 3 typedef long long LL; 4 const int maxn = 10001001; 5 LL phi[maxn], sum[maxn], n; 6 bool isprime[maxn]; 7 LL prime[maxn]; 8 int tot;

Codeforces 893E Counting Arrays:dp + 线性筛 + 分解质因数 + 组合数结论

题目链接:http://codeforces.com/problemset/problem/893/E 题意: 共q组数据(q <= 10^5),每组数据给定x,y(x,y <= 10^6). 问你有多少种长度为y,乘积为x的整数数列.(可以有负数) 题解: 首先考虑数列只有正整数的情况. 将x分解质因数:x = ∑ a[i]*p[i] 由于x较大,所以要先用线性筛求出素数,再枚举素数分解质因数. 那么一个乘积为x的数列可以看做,将x的所有∑ p[i]个质因子,分配到了y个位置上. 设f(i)

BZOJ 2693: jzptab [莫比乌斯反演 线性筛]

2693: jzptab Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 1194  Solved: 455[Submit][Status][Discuss] Description Input 一个正整数T表示数据组数 接下来T行 每行两个正整数 表示N.M Output T行 每行一个整数 表示第i组数据的结果 Sample Input 1 4 5 Sample Output 122 HINT T <= 10000 N, M<=1000000

jzp线性筛及其简单应用

前言: 很久以前看过了线性筛,没怎么注意原理,但是后来发现线性筛还有很有用的.. 比如上次做的一道题就需要找出每个数的最小质因子,先筛再找就太慢了..一看线性筛发现就可以直接在筛的过程中处理出来了! 今天又学习了屌炸天的jzp线性筛,可以在o(n)的时间内求出欧拉函数, 莫比乌斯函数等积性函数 原理: 首先jzp线性筛并不是一种新的线性筛..其实就是jzp大牛对线性筛的一些开发应用 先回忆一下积性函数的定义 若a,b互质 则f(ab)=f(a)*f(b)的函数f 定义为积性函数,不要求a,b互质

[原博客] 关于线性筛

埃氏筛法:从2开始,找到第一个没有被筛的数,把它标记为素数,然后把它的2倍.3倍……筛掉.复杂度O(nlogn). 改进的埃氏筛法:从2开始,找到第一个没有被筛的数x,把它标记为素数,然后把它的x倍.x+1倍……筛掉.复杂度O(nloglogn). 线性筛:保证每个数都被它的最小素因子筛掉.复杂度O(n). C++写起来大概是这样的: int mindiv[10000005],tot,prime[10000050]; int main(){ for(int i=2;i<=10000000;i++

【数论线性筛】洛谷P1865 A%B problem

题目背景 题目名称是吸引你点进来的 实际上该题还是很水的 题目描述 区间质数个数 输入输出格式 输入格式: 一行两个整数 询问次数n,范围m 接下来n行,每行两个整数 l,r 表示区间 输出格式: 对于每次询问输出个数 t,如l或r?[1,m]输出 Crossing the line 输入输出样例 输入样例#1: 2 5 1 3 2 6 输出样例#1: 2 Crossing the line 说明 [数据范围和约定] 对于20%的数据 1<=n<=10 1<=m<=10 对于100

洛谷 P3383 【模板】线性筛素数

P3383 [模板]线性筛素数 题目描述 如题,给定一个范围N,你需要处理M个某数字是否为质数的询问(每个数字均在范围1-N内) 输入输出格式 输入格式: 第一行包含两个正整数N.M,分别表示查询的范围和查询的个数. 接下来M行每行包含一个不小于1且不大于N的整数,即询问概数是否为质数. 输出格式: 输出包含M行,每行为Yes或No,即依次为每一个询问的结果. 输入输出样例 输入样例#1: 100 5 2 3 4 91 97 输出样例#1: Yes Yes No No Yes 说明 时空限制:5