P2350 外星人

Luogu 链接

题意

题目描述

定义一个函数 \(f(i,n)=\begin{cases}\varphi(n)&i=1\\\varphi(f(i-1,n))&i>1\end{cases}\)\(i\)\(n\) 都为正整数。

现已知一正整数 \(N\),求最小的 \(x\) 使得 \(f(x,N)=1\)


输入格式

多测,输入第一行为一个正整数 \(T\)\(1\le T\le50\)),表示有 \(T\) 组数据。

由于 \(N\) 可能非常大,读入时读入的是 \(N\) 的标准分解形式。

具体的,每组数据第一行一个正整数 \(m\),表示 \(N\)\(m\) 个互异的质因子。
接下来 \(m\) 行(\(m\le2000\)),每行有两个整数 \(p_i,q_i\)\(1\le p_i\le 10^5,1\le q_i\le 10^9\)),满足 \(\displaystyle \prod_{i = 1}^{m} p_i^{q_i}=N\)\(p_i\) 为互异的质数。


输出格式

题目描述

思路

由手玩易知只有 \(\varphi(2)\)\(\varphi(1)\) 等于 \(1\),并且对于任意正整数 \(n>2\),都有 \(2\mid\varphi(n)\)

并且注意到,每次操作(即计算 \(\varphi(n)\))后最多只会消去一个 \(2\)

因此我们只需要计算在不断的操作中,会产生几个 \(2\) 即可,这是因为产生几个 \(2\) 就会消去几个 \(2\),并且每次只会消去一个 \(2\)

\(g(n)\)\(n\) 在不断地操作 \(n\) 时产生的 \(2\) 的个数。

  • 首先有 \(g(2)=1\)
  • 其次若 \(n\) 为奇质数,则 \(g(n)=g(n-1)\)(因为 \(\varphi(n)=n-1\))。
  • 否则,设 \(a\)\(b\) 为满足 \(a\times b=n\) 的正整数,\(g(n)=g(a)+g(b)\)(可以理解为先计算 \(a\) 再计算 \(b\))。

就实现上来说,可以利用线性筛计算 \(g(n)\)

统计答案时,\(N\) 产生的 \(2\) 个数为 \(ans=\displaystyle\sum_{i=1}^mq_i\times g(p_i)\)

需要注意的是,若 \(N\) 为奇数,则 \(ans\) 还需要加 \(1\),因为第一次不会消去 \(2\)

程序

AC 记录

#include<cstdlib>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<queue>
#include<cstdio>
#include<iostream>
#include<vector>
#include<map>
#include<cmath>
#include<iomanip>
#include<string>
#include<stack>
#define re register
#define ll long long
#define ull unsigned long long
#define vl __int128
#define ld long double
#define LL 2e18
#define INT 1e9
#define INF 0x3f3f3f3f
#define lb(x) (x&(-x))
#ifdef __linux__
#define gc getchar_unlocked
#define pc putchar_unlocked
#else
#define gc _getchar_nolock
#define pc _putchar_nolock
#endif
int T=1;
using namespace std;
inline bool blank(const char x){return !(x^32)||!(x^10)||!(x^13)||!(x^9);}
template<typename Tp>inline void read(Tp &x){x=0;re bool z=true;re char a=gc();for(;!isdigit(a);a=gc())if(a=='-')z=false;for(;isdigit(a);a=gc())x=(x<<1)+(x<<3)+(a^48);x=(z?x:~x+1);}
inline void read(double &x){x=0.0;re bool z=true;re double y=0.1;re char a=gc();for(;!isdigit(a);a=gc())if(a=='-')z=false;for(;isdigit(a);a=gc())x=x*10+(a^48);if(a!='.')return x=z?x:-x,void();for(a=gc();isdigit(a);a=gc(),y/=10)x+=y*(a^48);x=(z?x:-x);}
inline void read(ld &x){x=0.0;re bool z=true;re ld y=0.1;re char a=gc();for(;!isdigit(a);a=gc())if(a=='-')z=false;for(;isdigit(a);a=gc())x=x*10+(a^48);if(a!='.')return x=z?x:-x,void();for(a=gc();isdigit(a);a=gc(),y/=10)x+=y*(a^48);x=(z?x:-x);}
inline void read(char &x){for(x=gc();blank(x)&&(x^-1);x=gc());}
inline void read(char *x){re char a=gc();for(;blank(a)&&(a^-1);a=gc());for(;!blank(a)&&(a^-1);a=gc())*x++=a;*x=0;}
inline void read(string &x){x="";re char a=gc();for(;blank(a)&&(a^-1);a=gc());for(;!blank(a)&&(a^-1);a=gc())x+=a;}
template<typename T,typename ...Tp>inline void read(T &x,Tp &...y){read(x),read(y...);}
template<typename T>inline void read(T *begin,T *end){re T *i;if(begin<end)for(i=begin;i<end;++i)read(*i);else for(i=begin-1;i>=end;--i)read(*i);}
template<typename Tp>inline void write(Tp x){if(!x)return pc(48),void();if(x<0)pc('-'),x=~x+1;re int len=0;re char tmp[64];for(;x;x/=10)tmp[++len]=x%10+48;while(len)pc(tmp[len--]);}
inline void write(const double x){re int a=6;re double b=x,c=b;if(b<0)pc('-'),b=-b,c=-c;re double y=5*powl(10,-a-1);b+=y,c+=y;re int len=0;re char tmp[64];if(b<1)pc(48);else for(;b>=1;b/=10)tmp[++len]=floor(b)-floor(b/10)*10+48;while(len)pc(tmp[len--]);pc('.');for(c*=10;a;a--,c*=10)pc(floor(c)-floor(c/10)*10+48);}
inline void write(const ld x){re int a=6;re ld b=x,c=b;if(b<0)pc('-'),b=-b,c=-c;re ld y=5*powl(10,-a-1);b+=y,c+=y;re int len=0;re char tmp[64];if(b<1)pc(48);else for(;b>=1;b/=10)tmp[++len]=floor(b)-floor(b/10)*10+48;while(len)pc(tmp[len--]);pc('.');for(c*=10;a;a--,c*=10)pc(floor(c)-floor(c/10)*10+48);}
inline void write(const pair<int,double>x){re int a=x.first;if(a<7){re double b=x.second,c=b;if(b<0)pc('-'),b=-b,c=-c;re double y=5*powl(10,-a-1);b+=y,c+=y;re int len=0;re char tmp[64];if(b<1)pc(48);else for(;b>=1;b/=10)tmp[++len]=floor(b)-floor(b/10)*10+48;while(len)pc(tmp[len--]);a&&(pc('.'));for(c*=10;a;a--,c*=10)pc(floor(c)-floor(c/10)*10+48);}else printf("%.*lf",a,x.second);}
inline void write(const pair<int,ld>x){re int a=x.first;if(a<7){re ld b=x.second,c=b;if(b<0)pc('-'),b=-b,c=-c;re ld y=5*powl(10,-a-1);b+=y,c+=y;re int len=0;re char tmp[64];if(b<1)pc(48);else for(;b>=1;b/=10)tmp[++len]=floor(b)-floor(b/10)*10+48;while(len)pc(tmp[len--]);a&&(pc('.'));for(c*=10;a;a--,c*=10)pc(floor(c)-floor(c/10)*10+48);}else printf("%.*Lf",a,x.second);}
inline void write(const char x){pc(x);}
inline void write(const bool x){pc(x?49:48);}
inline void write(char *x){fputs(x,stdout);}
inline void write(const char *x){fputs(x,stdout);}
inline void write(const string &x){fputs(x.c_str(),stdout);}
template<typename T,typename ...Tp> inline void write(T x,Tp ...y){write(x),write(y...);}
template<typename T>inline void write(T *begin,T *end,const char c=' '){re T *i;for(i=begin;i<end;++i)write(*i,c);}
template<typename T>inline void init(T *begin,T *end,const T& val=T()){re T* i;for(i=begin;i<end;++i)*i=val;}
template<typename T>inline T max(T *begin,T *end){re T *ans,*i;for(i=begin;i<end;++i)if(i==begin||*ans<*i)ans=i;return *ans;}
template<typename T>inline T min(T *begin,T *end){re T *ans,*i;for(i=begin;i<end;++i)if(i==begin||*i<*ans)ans=i;return *ans;}
template<typename T>inline T calc_sum(T *begin,T *end,const T& val=T()){re T ans=val,*i;for(i=begin;i<end;++i)ans+=*i;return ans;}
template<typename T>inline bool is_equal(T *begin,T *end,const T& val=T()){re T *i;for(i=begin;i<end;++i)if(*i!=val)return false;return true;}

ll mod=0;
const int MAXN=1e5;
const int N=MAXN+10;
//#define DEBUG
//#define more_text

ll n,m,p,q;

ll ans,P[N],g[N];bool np[N],has_two;
void init(){
	int cnt=0,len=MAXN;
	g[1]=1; //方便计算 
	for(int i=2;i<=len;++i){
		if(!np[i])P[++cnt]=i,g[i]=g[i-1];
		for(int j=1;j<=cnt&&i*P[j]<=len;++j){
			np[i*P[j]]=true;
			g[i*P[j]]=g[i]+g[P[j]];
			if(i%P[j]==0)break;
		}
	}
}

void solve(int step){
	init();
	read(T);
	
	while(T--){
		read(n);
		
		ans=0,has_two=false;
		
		for(int i=0;i<n;++i){
			read(p,q);
			if(p==2)has_two=true;
			ans+=g[p]*q;
		}
		if(!has_two)++ans;
		
		write(ans,'\n');
	}
}
/*
Input:

Output:

Outline:

*/
int main(){
	#ifdef DEBUG
	freopen("test.in","r",stdin);freopen("test.out","w",stdout);
	#endif
	#ifdef more_text
	read(T);
	#endif 
	for(int i=0;i<T;++i)solve(i);
	#ifdef DEBUG
	fclose(stdin);fclose(stdout);
	#endif
	return 0;
}
posted @ 2025-03-09 09:55  LXcjh4998  阅读(19)  评论(0)    收藏  举报