BZOJ 2749 HAOI2012外星人

Problem

BZOJ

Thoughts

FBI warning:Thoughts是错的,正解是下面的Solution
一开始看比较懵逼,然后就开始了大力推公式

第一次迭代

ϕ ( i = 1 m p i q i ) = i = 1 m ( p i 1 ) p i q i 1

第二次迭代

ϕ 2 ( i = 1 m ( p i 1 ) p i q i 1 ) = ϕ ( i = 1 m p i q i 1 i = 1 m ( p i 1 ) )

= i = 1 m ( p i 1 ) p i q i 2 i = 1 m ( p i 2 )

第k次迭代

ϕ k = i = 1 m ( p i 1 ) p i q i k i = 1 m ( p i k )

若为1,则 p i k 1 , ( q i k 0 | | p i 1 )

然而这并不对,因为拆开后的形式并不一定是标准分解,那么大力推公式就会有毛病

Solution

可以发现,做质因数分解之后,qi减小了1,而pi-1的指数增加了1,可以感性地理解为pi向pi-1,以及更多次迭代之后出现的所有质因数都汇聚了1的水,而自己的水量减小了1。其次,汇聚最多的应该是2,因为最后都会汇集到2,所以直接考虑2的贡献即可,在线性筛的时候处理。

如果你要理性地想。。就是由提示可以知道每次取phi,就是使得一个质因数pi变成pi-1,显然仅有phi(2)是等于1的,而每取一次phi,都只能化简一个2变为1。对于大于2的质数,都是奇数,那么p-1就是一个偶数,就必定可以得到因数2。注意当原来就没有pi=2时,由于第一次无法化简掉一个2,所以ans要+1。

Code

#include <cstdio>
#define rg register
using namespace std;
typedef long long ll;
const int maxn=100010;
int z,n,p,q,tot,pri[maxn],cnt[maxn];
ll ans;
template <typename Tp> inline void read(Tp &x)
{
    x=0;int f=0;char ch=getchar();
    while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
    if(ch=='-') f=1,ch=getchar();
    while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    if(f) x=-x;
}
void init()
{
    cnt[1]=1;
    for(rg int i=2;i<=100000;i++)
    {
        if(!cnt[i]) pri[++tot]=i,cnt[i]=cnt[i-1];
        for(int j=1;j<=tot&&i*pri[j]<=100000;j++)
        {
            cnt[i*pri[j]]=cnt[i]+cnt[pri[j]];
            if(i%pri[j]==0) break;
        }
    }
}
int main()
{
    #ifndef ONLINE_JUDGE
    freopen("in.txt","r",stdin);
    #endif
    init();
    read(z);
    while(z--)
    {
        read(n);ans=1;
        for(rg int i=1;i<=n;i++)
        {
            read(p);read(q);
            ans+=(ll)cnt[p]*q;
            if(p==2) ans--;
        }
        printf("%lld\n",ans);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/as_a_kid/article/details/80934041
今日推荐