数论·欧拉函数·[HAOI2012]外星人

[HAOI2012]外星人

题目大意:给定一个数N,问你这个数取多少次欧拉函数后变成1
题目类型:欧拉函数

Input
test(数据数量),每组一个m,接下来m个pi,qi,为n的标准分解形式

Output

输出test行整数

Sample Input

1 2
2 2
3 1

Sample Output

3

题解

注意到只有phi[2]=1,所以每个数最终都是要经过phi[2]=1这一步变为1

而每一次做欧拉函数,根据欧拉函数的计算式可以看出:会产生一个2,也必会消掉一个2. 每个pi做一次欧拉函数,就变成了pi-1,而pi减1必为合数,除非pi为2,pi-1又分解为若干个pi的qi次方,继续下去,直到pi为2,结束,则有多少个2,就需要多少次。 因此我们只需要算出原数N的质因子一共会产生多少个2即可 于是我们令f[i]表示i分解出了几个2: i为质数,f[i] = f[i - 1];否则,f[i * prime[j] = f[i] + f[prime[j]]
另:如果一开始n为奇数,则ans需+ 1,因为变出2需要第一步。 因为若开始是奇数,第一次做欧拉函数是不会消掉2的,且运作到中间不会出现没有2的情况,因为pi为奇数,pi-1则必定为偶数,2一定会有的。

代码

    #include<bits/stdc++.h>
    typedef long long ll;
    using namespace std;
    
    const ll M = 1e5+10;
    ll f[M], prime[M/2],cnt = 0,test;
    bool check[M];
    
    void make_prime(){
    	f[1] = 1;
    	for(ll i = 2; i <= M; i++){
    		if(!check[i]) prime[++cnt] = i,f[i] = f[i - 1];
    		for(ll j = 1; j <= cnt && i * prime[j] <= M; j++){
    			check[i * prime[j]] = 1;
    			f[i * prime[j]] = f[i] + f[prime[j]];
    			if(i%prime[j] == 0) break;
    		}
    	}
    }
    
    int main()
    {
    //	freopen("alien.in","r",stdin);
    //	freopen("alien.out","w",stdout);
    	scanf("%lld",&test);
    	make_prime();
    	while(test--){
    		ll ans = 1,m,pi,qi;
    		scanf("%lld",&m);
    		for(ll i = 1; i <= m;i++){
    			scanf("%lld%lld",&pi,&qi);
    			if(pi == 2) ans--;
    			ans += f[pi] * qi;
    		}
    		printf("%lld\n",ans);
    	}
    	return 0;
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值