2749: [HAOI2012]外星人

Time Limit: 3 Sec  Memory Limit: 128 MB
Submit: 377  Solved: 199
[Submit][Status]

Description

 

Input

 

Output

输出test行,每行一个整数,表示答案。

Sample Input

1
2
2 2
3 1

Sample Output

3

HINT

Test<=50 Pi<=10^5,1<=Q1<=10^9

Source

题解:

终于把这题搞掉了。。。

研究了一下此题的两种解法。

一种是直接求 这个数一直phi,最后能phi出多少个2,就是答案。

一种是利用递推的思想,用 f[i]表示i phi几次能变成1,有递推式 f[i]=f[phi(i)]+1

这两种方法都可以求出正确结果,让我们讨论一下为什么这样就可以:

首先,

题中给出了这样的公式,然后我们发现每次phi只能使每个质数的指数-1,然后这个 p[i]-1会继续质因数分解然后加在其它比它小的质数的指数上。

然后我们就会发现,2被phi的次数一定是最多的!!!

假设还有另一个质数 x 那么 phi(x)会多出1个2,所以 phi(2)的次数>=phi(x) 的次数!

所以 2被phi了多少次,ans就是多少!2还没有被phi完,其他质数的质数就已经都为0了!

然后呢?我们得到了一个什么结论?一个数被phi成1的次数就等于它phi了多少次2

这样的话 f[x]就等于 x phi 2的次数。

然后两种方法就统一了。

这也就解释了为什么不同的质数之间的被phi的次数是可以叠加的,因为我们加的实际上是同一个质数2的次数,而phi每次只能让2的指数-1!!!

还有一些细节要注意,这里就不提出了。

代码:直接递推求 f[x](求phi写萎了。。。)(这里面的偶数求的会比实际少1,因为并没有计入第一次phi的2)

 #include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int m=;
int p[m],f[m],n,t,i,j,x,y;
long long ans;
int main()
{
for(i=;i<=m;i++) p[i]=i;
for(i=;i<=m;i++)
if(p[i]==i)
for(j=i;j<=m;j+=i) p[j]=p[j]/i*(i-);
p[]=,f[]=-;
for(i=;i<=m;i++) f[i]=f[p[i]]+;
f[]++,f[]++;
cin>>t;
while(t--)
{
scanf("%d",&n);
for(ans=,i=;i<=n;i++)
{
scanf("%d%d",&x,&y);
if(x==) ans--;
ans+=(long long)f[x]*y;
}
printf("%lld\n",ans);
}
return ;
}

代码:求2的个数

 #include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<vector>
#include<map>
#include<set>
#include<queue>
#include<string>
#define inf 1000000000
#define maxn 100000+5
#define maxm 500+100
#define eps 1e-10
#define ll long long
#define pa pair<int,int>
#define for0(i,n) for(int i=0;i<=(n);i++)
#define for1(i,n) for(int i=1;i<=(n);i++)
#define for2(i,x,y) for(int i=(x);i<=(y);i++)
#define for3(i,x,y) for(int i=(x);i>=(y);i--)
#define mod 1000000007
using namespace std;
inline int read()
{
int x=;char ch=getchar();
while(ch<''||ch>''){ch=getchar();}
while(ch>=''&&ch<=''){x=*x+ch-'';ch=getchar();}
return x;
}
int tot,p[maxn],f[maxn];
bool v[maxn];
int main()
{
freopen("input.txt","r",stdin);
freopen("output.txt","w",stdout);
f[]=;
for2(i,,maxn)
{
if(!v[i]){p[++tot]=i;f[i]=f[i-];}
for1(j,tot)
{
int t=i*p[j];
if(t>maxn)break;
v[t]=;
f[t]=f[i]+f[p[j]];
if(i%p[j]==)break;
}
}
int m=read();
while(m--)
{
int n=read();ll ans=;
for1(i,n)
{
int x=read(),y=read();
if(x==)ans--;
ans+=(ll)f[x]*y;
}
printf("%lld\n",ans);
}
return ;
}

其实f[x]=求2的个数,这里只是用了不同的方法。

BZOJ2749: [HAOI2012]外星人的更多相关文章

  1. BZOJ2749 HAOI2012外星人(数论)

    不妨把求φ抽象成把将每个位置上的一个小球左移一格并分裂的过程,那么即求所有球都被移到1号格子的步数. 显然要达到1必须先到达2.可以发现每次分裂一定会分裂出2号位的球,因为2以外的质数一定是奇数.以及 ...

  2. 【bzoj2749】[HAOI2012]外星人

    2749: [HAOI2012]外星人 Time Limit: 3 Sec  Memory Limit: 128 MBSubmit: 677  Solved: 360[Submit][Status][ ...

  3. Bzoj 2749: [HAOI2012]外星人 欧拉函数,数论,线性筛

    2749: [HAOI2012]外星人 Time Limit: 3 Sec  Memory Limit: 128 MBSubmit: 568  Solved: 302[Submit][Status][ ...

  4. 【BZOJ 2749】 2749: [HAOI2012]外星人 (数论-线性筛?类积性函数)

    2749: [HAOI2012]外星人 Description Input Output 输出test行,每行一个整数,表示答案. Sample Input 1 2 2 2 3 1 Sample Ou ...

  5. [HAOI2012]外星人

    题目大意: 告诉你一个数n,求满足φ^x(n)=1的x. 思路: 首先我们可以发现满足φ(n)=1的数只有2,也就是说你得到最终的结果,最后一步肯定是φ(2). 同时,可以发现φ(φ(2^k))=φ( ...

  6. JZYZOJ1524 [haoi2012]外星人 欧拉函数

    http://172.20.6.3/Problem_Show.asp?id=1524 大概可以算一个结论吧,欧拉函数在迭代的时候,每次迭代之后消去一个2,每个非2的质因子迭代一次又(相当于)生成一个2 ...

  7. 题解 P2350 【[HAOI2012]外星人】

    题目链接 还是本宝宝写题解的一贯习惯 $ :$ 先吐槽吐槽这道题$……$ 相信不少同学第一眼一定没有看懂题.(因为我也没看懂) ~~初中~~数学知识: 对于函数 $ f(x)$ 有 $f^{-1}(x ...

  8. 2749: [HAOI2012]外星人

    首先像我一样把柿子画出来或者看下hint 你就会发现其实是多了个p-1这样的东东 然后除非是2他们都是偶数,而2就直接到0了 算一下2出现的次数就好 #include<cstdio> #i ...

  9. BZOJ 2749 [HAOI2012]外星人

    题解:对每一个>2的质数分解,最后统计2的个数 注意:如果一开始没有2则ans需+1,因为第一次求phi的时候并没有消耗2 WA了好几遍 #include<iostream> #in ...

随机推荐

  1. jquery之获取当前时间

    /** * * 获取当前时间 */ function p(s) { return s < 10 ? '0' + s: s; } var myDate = new Date(); //获取当前年 ...

  2. 使用MiniProfiler调试Asp.net Mvc性能

    使用nuget添加MiniProfiler.EF组件 在Global文件中配置MiniProfiler protected void Application_Start() { AreaRegistr ...

  3. carousel

    <!DOCTYPE html> <html lang="en" ng-app="mainApp"> <head> <m ...

  4. Java遍历Map、List、Array

    1.遍历array,使用for循环或者foreach(本人建议使用) int arr[] = {2, 3, 1}; System.out.println("----1----排序前的一维数组 ...

  5. Linq101-Quantifiers

    using System; using System.Collections.Generic; using System.Linq; namespace Linq101 { class Quantif ...

  6. ASP.NET中 分析器错误:发现不明确的匹配

    这是一个不好的代码习惯引起的发布后运行时的问题.错误原因为.net2.0无法正确识别服务器控件和变量的大小写区别,但是这个错误只有在iis中体现,在文件系统的调试中没有发生. 错误信息 引发错误的参考 ...

  7. CXF处理Date类型的俩种方式

    1. CXF利用wsdl2java生成客户端时Date日期类型转换 http://cwfmaker.iteye.com/blog/1142835 2. GregorianCalendar cal = ...

  8. Swift - 08 - 元组

    //: Playground - noun: a place where people can play import UIKit // 元组就是将多个不同的值集合成一个数据 /* 元组是Object ...

  9. 一种实现C++反射功能的想法(一)

    Java的反射机制很酷, 只需知道类的名字就能够加载调用. 这个功能很实用, 想象一下, 用户只需指定类的名称, 就可以动态绑定类型, 而且只需通过字符串指定, 字符串的使用可以使得用户的修改只需修改 ...

  10. [LeetCode OJ] Single Number之一 ——Given an array of integers, every element appears twice except for one. Find that single one.

    class Solution { public: int singleNumber(int A[], int n) { int i,j; ; i<n; i++) { ; j<n; j++) ...