PKU 2649-Factovisors

問題概要

n!がmで割り切れるか判定せよ

解法(C++)

コーナーケースゲー.n=0またはm=0に注意.
n!が素因数pで割り切れる回数はn/pを0になるまで繰り返すことで求めることが出来るので,
mを素因数分解して,n!に表われる回数以上か調べる.

実装(C++)

酷すぎる実装.

#include <vector>
#include <iostream>
#include <algorithm>
#include <cmath>
#include <map>
#define REP(i,x) for(int i=0;i<(int)x;i++)
#define FOR(i,c) for(__typeof((c).begin())i=(c).begin();i!=(c).end();i++)
using namespace std;
const int sieve_max=65536; //予め計算しておく素数の最大値
vector<bool> eratosthenes_sieve(int n){
	vector<bool> res(n+1);
	res[0]=res[1]=false;res[2]=true;
	int i,j,m=sqrt(n)+1e-9;
	for(i=3;i<=n;i+=2){
		if(i<=m){
			if(res[i]==false){
				for(j=i+i+i;j<=n;j+=i+i){
					res[j]=true;
				}
			}
		}
		res[i]=!res[i];
	}
	return res;
}

vector<int> prime_list(const vector<bool>& isprime){
	vector<int> res;if(isprime.size()<=2)return res;
	res.push_back(2);
	for(unsigned int i=3;i<isprime.size();i+=2)
		if(isprime[i])res.push_back(i);
	return res;
}
vector<int> prime_list(int n){
	return prime_list(eratosthenes_sieve(n));
}
vector<int> primes=prime_list(sieve_max);
long long mod_pow(long long a,long long n,long long M){
	if(n==0)return 1;
	long long res=mod_pow(a*a%M,n/2,M);
	if(n&1)res=res*a%M;
	return res;
}
bool miller_rabin(long long n){
	if(n==2)return true;if((n&1)==0||n<=1) return false;
	int a[]={2,7,61,-1},r;long long s=0,d,x;
	d=n-1;
	while((d&1)==0)s++,d=d>>1;
	for(int i=0;a[i]!=-1&&a[i]<n;i++){
		if((x=mod_pow(a[i],d,n))!=1){
			for(r=0;r<s;r++){
				if(x==n-1)break;
				x=(x*x)%n;
			}
			if(r==s)return false;
		}
	}
	return true;
}
inline long long random(long long x,long long c,long long m){
	return (x*x%m+c)%m;
}
int constant[5]={1,51,73,0};
long long absll(long long v){
	if(v<0)return -v;
	return v;
}
void pollards_rho(long long v,vector<long long>& res,bool precheck=true){//resに素因数分解の結果が入る
	if(precheck){
		REP(i,primes.size()){
			while((v%primes[i])==0){
				v/=primes[i];
				res.push_back(primes[i]);
			}
		}
		if(v==1)return;
	}
	if(miller_rabin(v)){
		res.push_back(v);
		return;
	}
	long long x=2,y=2,d=1;

	for(int i=0;constant[i];i++){
		while(d==1){
			x=random(x,constant[i],v);
			y=random(random(y,constant[i],v),constant[i],v);
			d=__gcd(absll(x-y),v);
		}
		if(d==v)continue;;
		pollards_rho(d,res,false);
		pollards_rho(v/d,res,false);
		return;
	}
}
typedef long long lli;
//m!に素因数pはいくつ含まれるか
lli count(lli m,lli p){
	lli res=0;
	while(m){
		res+=m/p;
		m/=p;
	}
	return res;
}
bool solve(lli n,lli m){
	vector<lli> f;
	if(n==0)n=1;
	pollards_rho(m,f);
	map<int,int> s;
	REP(i,f.size()){
		s[f[i]]++;
	}
	FOR(it,s){
		if(count(n,it->first)<it->second)return false;
	}
	return true;
}
int main() {
	int n,m;
	for(;cin>>n>>m;){
		if(m!=0&&solve(n,m)){
			cout<<m<<" divides "<<n<<"!"<<endl;
		}else{
			cout<<m<<" does not divide "<<n<<"!"<<endl;
		}
	}
	return 0;
}