CodeForces 542D. Superhero's Job 暴力数论

2024-08-21 08:08

本文主要是介绍CodeForces 542D. Superhero's Job 暴力数论,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

看出这一点,接下来只需要对A进行上述分解,有多少种分解,就有多少个答案。

由于每个p都是不一样的,所以找出的因子一定没有相等的,于是每种分解都可以按照从小到大排列。

于是每找出一个因子,都记下这个因子,并在接下来的寻找中,

忽略这个因子对应的质数,并且忽略小于这个因子的分解,这样可以避免重复,具体见代码。

简单来说,就是暴力递归出所有分解。

CF上的题解是用的DP,不过我暴力分解也过了。又一道被我暴力水过的,标答是DP的数论题

只能说数论题一般的分解情况比较少,暴力+优化就过了。这题,答案将近100万的都可以在1s内跑完暴力程序。

给一个大的例子:A=963761198400 时,答案为 100049


代码:

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#define out(i) <<#i<<"="<<(i)<<"  "
#define OUT1(a1) cout out(a1) <<endl
#define OUT2(a1,a2) cout out(a1) out(a2) <<endl
#define OUT3(a1,a2,a3) cout out(a1) out(a2) out(a3)<<endl
#define maxn 1000007 
#define LL long long
using namespace std;
int maxprime[maxn];//maxprime[i]:i的最大质因数 
int prime[100000],N;//prime[i]:第i个质数 
int keyprime[maxn];//keyprime[i]:若i=1+p^k 则keyprime[i]=k 否则 keyprime[i]=0 
int nextkeyprime[maxn];//记录下一个不为零的keyprime,加快计算过程 
void Init(){//初始化 memset(maxprime,0,sizeof(maxprime));memset(keyprime,0,sizeof(keyprime));keyprime[1]=1;N=0;for(int i=2;i<maxn;++i){if(maxprime[i]) continue;prime[N++]=i;for(int j=i;j<maxn;j+=i) maxprime[j]=i;for(LL j=1;j<=(maxn-2)/i;){j*=i;keyprime[j+1]=i;}}nextkeyprime[maxn-1]=maxn-1;for(int i=maxn-1;i>0;--i){if(keyprime[i]) nextkeyprime[i-1]=i;else nextkeyprime[i-1]=nextkeyprime[i];}
}
int Sqrt(LL x){//求floor(sqrt(x)) LL L=1,R=1000007;//[L,R)while(L+1 < R){LL M=(L+R)>>1;if(M*M <= x) L=M;else R=M;}return (int)L;
}
LL KeyPrime(LL x){//求x是否为某质数p的某个正次方 ,是的话返回这个质数,否则返回0 if(x+1 < maxn) return keyprime[x+1];//对于小的x直接利用keyprime数组 int KeyP=0;int sqx=Sqrt(x);for(int i=0;i<N;++i){if(x%prime[i]==0) {KeyP=prime[i];break;}if(prime[i]>sqx) break;//及时退出 }if(KeyP){while(x%KeyP==0) x/=KeyP;if(x==1) return KeyP;else return 0;}else return x;//此时x就是个大质数 
}LL x;
int p[20],n;//记录已经进行的分解中用到的质数 
bool exist(int k){//判断k是否存在for(int i=0;i<n;++i) if(p[i]==k) return true;return false;
}
int ANS;
void F(LL x,LL v){//x:当前待分解的数,v:当前因数的最大值 int top=Sqrt(x);LL KP=KeyPrime(x-1);//判断x是否可以被分解成1+p^k if(KP&&!exist(KP)) ++ANS;//如果这个因子没出现过,答案+1 p[n++]=KP;//除掉最小的因子,继续递归 for(int i=nextkeyprime[v];i<=top;i=nextkeyprime[i]){//OUT2(i,top);if(x%i==0&&!exist(keyprime[i])){p[n++]=keyprime[i];F(x/i,i);--n;}}--n;
}
int main(void)
{Init();while(cin>>x){int sqx=Sqrt(x);n=0;ANS=0;F(x,2);cout<<ANS <<endl;}
return 0;
}




 

这篇关于CodeForces 542D. Superhero's Job 暴力数论的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1092597

相关文章

数论入门整理(updating)

一、gcd lcm 基础中的基础,一般用来处理计算第一步什么的,分数化简之类。 LL gcd(LL a, LL b) { return b ? gcd(b, a % b) : a; } <pre name="code" class="cpp">LL lcm(LL a, LL b){LL c = gcd(a, b);return a / c * b;} 例题:

数论ZOJ 2562

题意:给定一个数N,求小于等于N的所有数当中,约数最多的一个数,如果存在多个这样的数,输出其中最大的一个。 分析:反素数定义:对于任何正整数x,其约数的个数记做g(x).例如g(1)=1,g(6)=4.如果某个正整数x满足:对于任意i(0<i<x),都有g(i)<g(x),则称x为反素数。 性质一:一个反素数的质因子必然是从2开始连续的质数。 性质二:p=2^t1*3^t2*5^t3*7

Codeforces Round #240 (Div. 2) E分治算法探究1

Codeforces Round #240 (Div. 2) E  http://codeforces.com/contest/415/problem/E 2^n个数,每次操作将其分成2^q份,对于每一份内部的数进行翻转(逆序),每次操作完后输出操作后新序列的逆序对数。 图一:  划分子问题。 图二: 分而治之,=>  合并 。 图三: 回溯:

Codeforces Round #261 (Div. 2)小记

A  XX注意最后输出满足条件,我也不知道为什么写的这么长。 #define X first#define Y secondvector<pair<int , int> > a ;int can(pair<int , int> c){return -1000 <= c.X && c.X <= 1000&& -1000 <= c.Y && c.Y <= 1000 ;}int m

Codeforces Beta Round #47 C凸包 (最终写法)

题意慢慢看。 typedef long long LL ;int cmp(double x){if(fabs(x) < 1e-8) return 0 ;return x > 0 ? 1 : -1 ;}struct point{double x , y ;point(){}point(double _x , double _y):x(_x) , y(_y){}point op

Codeforces Round #113 (Div. 2) B 判断多边形是否在凸包内

题目点击打开链接 凸多边形A, 多边形B, 判断B是否严格在A内。  注意AB有重点 。  将A,B上的点合在一起求凸包,如果凸包上的点是B的某个点,则B肯定不在A内。 或者说B上的某点在凸包的边上则也说明B不严格在A里面。 这个处理有个巧妙的方法,只需在求凸包的时候, <=  改成< 也就是说凸包一条边上的所有点都重复点都记录在凸包里面了。 另外不能去重点。 int

Codeforces 482B 线段树

求是否存在这样的n个数; m次操作,每次操作就是三个数 l ,r,val          a[l] & a[l+1] &......&a[r] = val 就是区间l---r上的与的值为val 。 也就是意味着区间[L , R] 每个数要执行 | val 操作  最后判断  a[l] & a[l+1] &......&a[r] 是否= val import ja

POJ2247数论

p = 2^a*3^b*5^c*7^d 求形如上式的第n小的数。 import java.io.BufferedReader;import java.io.InputStream;import java.io.InputStreamReader;import java.io.PrintWriter;import java.math.BigInteger;import java.u

计蒜客 Half-consecutive Numbers 暴力打表找规律

The numbers 11, 33, 66, 1010, 1515, 2121, 2828, 3636, 4545 and t_i=\frac{1}{2}i(i+1)t​i​​=​2​​1​​i(i+1), are called half-consecutive. For given NN, find the smallest rr which is no smaller than NN

CSP-J基础之数学基础 初等数论 一篇搞懂(一)

文章目录 前言声明初等数论是什么初等数论历史1. **古代时期**2. **中世纪时期**3. **文艺复兴与近代**4. **现代时期** 整数的整除性约数什么样的整数除什么样的整数才能得到整数?条件:举例说明:一般化: 判断两个数能否被整除 因数与倍数质数与复合数使用开根号法判定质数哥德巴赫猜想最大公因数与辗转相除法计算最大公因数的常用方法:举几个例子:例子 1: 计算 12 和 18