zoukankan      html  css  js  c++  java
  • 第四场 hdu 6069 Counting Divisors (逆向思维)

    http://acm.hdu.edu.cn/showproblem.php?pid=6069

    题目大意:求 i 从 l 到 r 中 i 的k次方的因子数之和。

    解题思路:我们可以知道一个数有因子,则这个数的因子一定是若干个质数因子排列组合得到的。我们首先要得到10^6中的素数,然后它的因子数量是 相同质因子数量+1 的乘积,所以我们能够想到从 l 到 r 枚举每一个i得到其 相同质因子数量+1 的乘积 的累加和。但是这样在枚举时会发现有一些质数是并不是所求的 i 的因子,所以我们应该反过来考虑,对于每一个质因子找出 l 到 r 中它的倍数,这样时间就被缩短了。

    AC代码:

     1 #include <iostream>
     2 #include <bits/stdc++.h>
     3 using namespace std;
     4 const int maxn=1100000;
     5 const long long SMod=998244353;
     6 bool is_prime[maxn+1];
     7 long long  prime[maxn],tmp[maxn],in[maxn];
     8 int sieve(int n)
     9 {
    10     int p=0;
    11     for(int i=0; i<=n; i++) is_prime[i]=true;
    12     is_prime[0]=is_prime[1]=false;
    13     for(int i=2; i<=n; i++)
    14     {
    15         if(is_prime[i])
    16         {
    17             prime[p++]=i;
    18             for(int j=2*i; j<=n; j=j+i)
    19                 is_prime[j]=false;
    20         }
    21     }
    22     return p;
    23 }
    24 int main()
    25 {
    26     sieve(1000007);
    27 //    for(int i=0;i<10;i++)
    28 //    printf("%d
    ",prime[i]);
    29     //freopen("1003.in","r",stdin);
    30     //freopen("out.txt","w",stdout);
    31     int t;
    32     long long l,r,k,ans,cnt,num;
    33     scanf("%d",&t);
    34     while(t--)
    35     {
    36         scanf("%lld%lld%lld",&l,&r,&k);
    37         int len=r-l;
    38         for(int i=0; i<=len; i++)
    39         {
    40             tmp[i]=1;
    41             in[i]=i+l;
    42         }
    43         ans=0;
    44         num=0;
    45         for(int i=0; prime[i]*prime[i]<=r&&i<78498; i++)
    46         {
    47             int p=prime[i];
    48             for(int j=l/p*p-l; j<=len; j+=p)
    49             {
    50                 if(j<0)
    51                     continue;
    52                 num=0;
    53                 while(in[j]%p==0)
    54                 {
    55                     num++;
    56                     in[j]=in[j]/p;
    57                 }
    58                 tmp[j]=(tmp[j]*(((num*k)%SMod)+1))%SMod;
    59             }
    60         }
    61         for(int i=0; i<=len; i++)
    62         {
    63             if(in[i]>1)
    64                 tmp[i]=(tmp[i]*(k+1))%SMod;
    65             //printf("%lld %lld %lld
    ",in[i],l+i,tmp[i]);
    66             ans=(ans+tmp[i])%SMod;
    67             //printf("%lld
    ",ans);
    68         }
    69         printf("%lld
    ",ans);
    70     }
    71     return 0;
    72 }

    这个代码挺奇怪的我感觉都对,但是15个数据过了14个就倒数第二个错了郁闷啊>_<||| 。

    求大神指点一下

     1 #include <iostream>
     2 #include <bits/stdc++.h>
     3 using namespace std;
     4 const int maxn=1100000;
     5 const long long SMod=998244353;
     6 bool is_prime[maxn+1];
     7 long long  prime[maxn],tmp[maxn],in[maxn];
     8 int sieve(int n)
     9 {
    10     int p=0;
    11     for(int i=0; i<=n; i++) is_prime[i]=true;
    12     is_prime[0]=is_prime[1]=false;
    13     for(int i=2; i<=n; i++)
    14     {
    15         if(is_prime[i])
    16         {
    17             prime[p++]=i;
    18             for(int j=2*i; j<=n; j=j+i)
    19                 is_prime[j]=false;
    20         }
    21     }
    22     return p;
    23 }
    24 int main()
    25 {
    26     sieve(1000007);
    27 //    for(int i=0;i<10;i++)
    28 //    printf("%d
    ",prime[i]);
    29     //freopen("1003.in","r",stdin);
    30     //freopen("out.txt","w",stdout);
    31     int t;
    32     long long l,r,k,ans,cnt,num;
    33     scanf("%d",&t);
    34     while(t--)
    35     {
    36         scanf("%lld%lld%lld",&l,&r,&k);
    37         int len=r-l;
    38         for(int i=0; i<=len; i++)
    39         {
    40             tmp[i]=1;
    41             in[i]=1;
    42         }
    43         ans=0;
    44         num=0;
    45         for(int i=0; prime[i]*prime[i]<=r&&i<78498; i++)
    46         {
    47             int p=prime[i];
    48             int it=prime[i]-(l%prime[i]);
    49             if(it==prime[i])
    50                 it=0;
    51             if(it>len)
    52             continue;
    53             for(int j=it; j<=len;)
    54             {
    55                 long long data=j+l;
    56                 while(data%p==0)
    57                 {
    58                     num++;
    59                     data=data/p;
    60                     in[j]=in[j]*p;
    61                 }
    62                 if(num!=0)
    63                 {
    64                     tmp[j]=(tmp[j]*(((num*k)%SMod)+1))%SMod;
    65                     num=0;
    66                 }
    67                 j=j+p;
    68             }
    69         }
    70         for(int i=0; i<=len; i++)
    71         {
    72             if(in[i]*in[i]<i+l)
    73             tmp[i]=tmp[i]*(k+1);
    74             //printf("%lld %lld %lld
    ",in[i],l+i,tmp[i]);
    75             if(l+i==1)
    76             {
    77                 ans=(ans+1)%SMod;
    78             }
    79             else if(tmp[i]==1)
    80             {
    81                 ans=(ans+2)%SMod;
    82             }
    83             else
    84             {
    85                 ans=(ans+tmp[i])%SMod;
    86             }
    87         }
    88         printf("%lld
    ",ans);
    89     }
    90     return 0;
    91 }
  • 相关阅读:
    Python 安装Twisted 提示python version 2.7 required,which was not found in the registry
    Openfire Strophe开发中文乱码问题
    css div 垂直居中
    How to create custom methods for use in spring security expression language annotations
    How to check “hasRole” in Java Code with Spring Security?
    Android 显示/隐藏 应用图标
    Android 当媒体变更后,通知其他应用重新扫描
    文件上传那些事儿
    专题:点滴Javascript
    主流动画实现方式总结
  • 原文地址:https://www.cnblogs.com/wang-ya-wei/p/7286892.html
Copyright © 2011-2022 走看看