zoukankan      html  css  js  c++  java
  • LightOJ

    先上题目

    1054 - Efficient Pseudo Code
    Time Limit: 1 second(s) Memory Limit: 32 MB

    Sometimes it's quite useful to write pseudo codes for problems. Actually you can write the necessary steps to solve a particular problem. In this problem you are given a pseudo code to solve a problem and you have to implement the pseudo code efficiently. Simple! Isn't it? :)

    pseudo code

    {

        take two integers n and m

        let p = n ^ m (n to the power m)

        let sum = summation of all the divisors of p

        let result = sum MODULO 1000,000,007

    }

    Now given n and m you have to find the desired result from the pseudo code. For example if n = 12 and m = 2. Then if we follow the pseudo code, we get

    pseudo code

    {

        take two integers n and m

        so, n = 12 and m = 2

        let p = n ^ m (n to the power m)

        so, p = 144

        let sum = summation of all the divisors of p

        so, sum = 403, since the divisors of p are 1, 2, 3, 4, 6, 8, 9, 12, 16, 18, 24, 36, 48, 72, 144

        let result = sum MODULO 1000,000,007

        so, result = 403

    }

    Input

    Input starts with an integer T (≤ 5000), denoting the number of test cases.

    Each test case will contain two integers, n (1 ≤ n) and m (0 ≤ m). Each of n and m will be fit into a 32 bit signed integer.

    Output

    For each case of input you have to print the case number and the result according to the pseudo code.

    Sample Input

    Output for Sample Input

    3

    12 2

    12 1

    36 2

    Case 1: 403

    Case 2: 28

    Case 3: 3751

      这一题的题意很简单,就是给你2个数n,m求n的m次幂的因子和是多少,当然,结果要模1000000007。这一题的要求其实有两个,一是不超时,二是得到正确的答案,则用普通的pow函数配合求因子明显不行。

      首先,因为数字很大,如果先pow在求模明显早溢出了,其次,太大的数字求因子和明显慢得像蜗牛。所以这一题需要自己写一个快速幂,同时要知道一件事就是我们不需要一开始就算出pow(n,m)出来,由素数唯一分解定理可以得到,pow(n,m)的分解出来的素数种类和n分解出来的种类是一样的只是数目上是n的各个素数的数目的m倍,所以我们可以先求出n的素数,然后每一个的含有数目都乘上m即可,然后就是求因子和了。求因子和需要求每一个素数的p^αi这一个等比数列,然后根据乘法原理求出结果,就是因子和这里可以很好地理解,每一个素数出现有0~p^αi这么多种状态,它们和其他素数的不同状态组合起来就得到所有的结果了。这里有很多方法,师兄的代码是用逆元来解,但是暂时我还不懂逆元怎样用,而且师兄说过这种方法有局限,因此这里我使用的是另一种解法,就是二分求等比数列。分析如下图

      代码可以对两种情况进行完全分开的写求值过程,而不是偶数时前半部分化为奇数情况调用,前者大概会快一点。(= =反正两种我都试过了)

    上代码:

      1 #include <stdio.h>
      2 #include <string.h>
      3 #include <math.h>
      4 #define MOD 1000000007
      5 #define LL long long
      6 #define MAX (1<<16)+10
      7 using namespace std;
      8 
      9 LL pri[MAX];
     10 int tot;
     11 bool mark[MAX];
     12 
     13 void dedeal()
     14 {
     15     LL i,n,j;
     16     n=MAX-10;
     17     memset(pri,0,sizeof(pri));
     18     memset(mark,0,sizeof(mark));
     19     for(i=2;i<=n;i++)
     20     {
     21         if(!mark[i])
     22         {
     23             pri[tot++]=i;
     24             for(j=i*i;j<=n;j+=i)
     25             {
     26                 mark[j]=1;
     27             }
     28         }
     29     }
     30 }
     31 
     32 LL FastMod(LL a,LL q)
     33 {
     34     if(q==0) return 1;
     35     LL t=FastMod(a,q>>1);
     36     t=t%MOD;
     37     t=t*t%MOD;
     38     if(q&1) t=t*a%MOD;
     39     return t;
     40 }
     41 
     42 /*
     43 LL FastMod(LL a,LL q)
     44 {
     45     LL k,r;
     46     if(!q) return 1;
     47     k=1;
     48     r=a%MOD;
     49     while(q>1)
     50     {
     51         if(q&1) k=k*r%MOD;
     52         r=r*r%MOD;
     53         q>>=1;
     54     }
     55     return r*k%MOD;
     56 }
     57 */
     58 LL f(LL a,LL q)
     59 {
     60     if(q==0) return 1;
     61     if(q&1) return (f(a,q>>1)%MOD*(1+FastMod(a,(q+1)>>1)))%MOD;
     62     return (f(a,q-1)%MOD+FastMod(a,q))%MOD;
     63 }
     64 
     65 LL fs(LL n,LL M)
     66 {
     67     LL i,m,sum,amo;
     68     i=0;
     69     m=sqrt(n);
     70     sum=1;
     71     for(i=0;i<tot && pri[i]<=m;i++)
     72     {
     73         if(n%pri[i]==0)
     74         {
     75             amo=0;
     76             //printf("%lld ",pri[i]);
     77             while(n%pri[i]==0) {n/=pri[i];amo++;}
     78             sum=sum*f(pri[i],(amo*M))%MOD;
     79         }
     80         if(n==1) break;
     81     }
     82     if(n>1) sum=sum*f(n,M)%MOD;
     83     return sum%MOD;
     84 }
     85 
     86 int main()
     87 {
     88     int t,i;
     89     LL n,m,sum;
     90     //freopen("data.txt","r",stdin);
     91     dedeal();
     92     scanf("%d",&t);
     93     for(i=1;i<=t;i++)
     94     {
     95         scanf("%lld %lld",&n,&m);
     96         sum=fs(n,m);
     97         printf("Case %d: %lld
    ",i,sum%MOD);
     98     }
     99     return 0;
    100 }
    1054
  • 相关阅读:
    20175202 《Java程序设计》第六周学习总结
    2018-2019-2 20175202实验一《Java开发环境的熟悉》实验报告
    20175202 《Java程序设计》迭代和JDB
    20175202 《Java程序设计》第五周学习总结
    20175202 《Java程序设计》第三周学习总结
    20175202 《Java程序设计》第四周学习总结
    第六周学习总结
    java第一次实验
    第五次学习总结
    第四次学习总结
  • 原文地址:https://www.cnblogs.com/sineatos/p/3228823.html
Copyright © 2011-2022 走看看