zoukankan      html  css  js  c++  java
  • hdu 4704 sum(费马小定理+快速幂)

    题意:

      这题意看了很久。。

        s(k)表示的是把n分成k个正整数的和,有多少种分法。

      例如:

    n=4时,

    s(1)=1     4

      s(2)=3     1,3      3,1       2,2

         s(3)=3     1,1,2         1,2,1       2,1,1

        s(4)=1       1,1,1,1

    s(1)+s(2)+s(3)+s(4)=1+3+3+1=8

    当n=1,2,3,4时,可以分别求出结果为    1,2,4,8

    于是推出答案就是2^(n-1)---------------------(为什么?我也不知道,这个是怎么推出来的)


    思路:题意明白了,就是求2^(n-1)    mod(10^9+7)呗。

    由于这里的n非常大,1<=n<10^100000,这里用简单的暴力绝对超时啊(10^8就会超时)

    那么,这里用了两个优化,一个是费马小定理 a^(p-1)≡1(mod p),另外就是快速幂加速求幂

    这里稍微演示一下如何利用费马小定理处理:



    (单单用费马小定理处理仍会超时,因为处理完后,指数最大能达到10^9级别,仍会超时)


    代码:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    const int mod=1e9+7;
    
    void pow(__int64 b){//快速求幂(位操作)
    	__int64 a=2;
    	__int64 ans;
    	ans=1;
    	while(b>0){
    		if(b&1)//判断是否为奇数,相当于 if(b%2==1)
    			ans=(ans*a)%mod;
    		a=(a*a)%mod;
    		b=b>>1;//二进制向右移一位,相当于 b=b/2;
    	}
    	printf("%I64d
    ",ans);
    }
    
    int main(){
    	char str[123456];
    	__int64 num,i;
    	while(~scanf("%s",str)){
    		num=0;
    		int len=strlen(str);
    		for(i=0;i<len;i++){
    			num=( num*10+(str[i]-'0') )% (mod-1);//精华部分
    		}
    		if(num==0) pow(mod-2);//此时n=mod-1,所以应该求pow(mod-2),而不能求成pow(num-1)
    		else pow(num-1);
    	}
    	return 0;
    }
    



  • 相关阅读:
    CentOS7 搭建php环境
    多tomcat服务和nginx负载均衡配置
    linux grep命令
    centos7 远程连接其他服务器redis
    centos7 远程连接其他服务器mysql
    关于结构体对齐
    c语言打印一个整数的二进制形式
    c语言判断一个数是否为偶数
    vim的窗口切换
    pow(x,y)函数的实现算法(递归函数)
  • 原文地址:https://www.cnblogs.com/gongpixin/p/4477371.html
Copyright © 2011-2022 走看看