Codechef November Challenge 2015 Simple Sum

题意:

NK=1Ngcd(N,K) . 有 106 个询问, N107

思路:

首先证明出
答案应该是 dφ(d) 对所有的 d N 的约数。

这个具体的证明可以参考 SPOJ LCMSUM (数论),然后如果我们先线性预处理出了 1 - 107 内的欧拉函数 phi[i] ,后面再枚举约数,考虑每个约数的贡献算出所有的答案,这样的话最短时间也是 3s 左右,但是题目要求 1s .

注意到关于欧拉函数的下列性质:

证明

所以我们可以利用性质1和2,做到 logN 内回答每一个询问:
N=kpe , p为最大的质数,这个可以预处理的。
由性质1:

ans=d|Ndφ(d)=α=0ed|kdpαφ(dpα)=α=0ed|kdφ(d)pαφ(pα)=(α=0epαφ(pα))d|kdφ(d),

第一部分可以由性质2得到,第二部分就直接计算咯(也可以实现预处理 ans[i] 1i106 )!

代码:
#include <bits/stdc++.h>
#define dibs reserve
#define OVER9000 1234567890
#define ALL_THE(CAKE,LIE) for(auto LIE =CAKE.begin(); LIE != CAKE.end(); LIE++)
#define tisic 47
#define soclose 1e-8
#define chocolate win
// so much chocolate
#define patkan 9
#define ff first
#define ss second
#define abs(x) ((x < 0)?-(x):x)
#define uint unsigned int
#define dbl long double
#define pi 3.14159265358979323846
using namespace std;
// mylittledoge

int main()
{
    cin.sync_with_stdio(0);
    cin.tie(0);
    int mx =10000000;
    vector<int> minD(mx+tisic,0);
    for(int i =2; i <= mx; i++) if(minD[i] == 0)
        for(int j =1; j <= mx/i; j++) minD[i*j] =i;
    int T;
    scanf(" %d",&T);
    while(T--) {
        int N;
        long long ans =1;
        scanf(" %d",&N);
        while(N > 1) {
            int p =minD[N], ppw =1;
            while(N%p == 0) {
                ppw *=p;
                N /=p;
            }
            ans *=1LL*ppw*ppw-(1LL*ppw*ppw-1)/(p+1);
        }
            printf("%lld\n",ans);
    }
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值