HDU 6467 简单数学题 【递推公式 && O(1)优化乘法】(广东工业大学第十四届程序设计竞赛)

传送门:http://acm.hdu.edu.cn/showproblem.php?pid=6467

 

简单数学题

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 308    Accepted Submission(s): 150


Problem Description
已知

F(n)=i=1n(i×j=inCij)


求 F(n) mod 1000000007
 

 

Input
多组输入,每组输入占一行,包含一个整数n(1 <= n <= 1e18)。
数据不超过300000组。
 

 

Output
对于每组输入,输出一行,包括一个数代表答案。
 

 

Sample Input
5 100
 

 

Sample Output
129 660756544
 

 

Source

 

 

 

 

 

 

 

 

解题思路:

 

但是这道题只推出递推公式是不行的,因为普通的乘法运算会导致溢出。

但是log2的优化乘法又会超时,所以需要O(1)的优化乘法防止溢出:

inline long long multi(long long x,long long y)
{
    long long tmp=(x*y-(long long)((long double)x/mod*y+1.0e-8)*mod);
    return tmp<0 ? tmp+mod : tmp;
}

 

AC code:

 1 #include <bits/stdc++.h>
 2 #define INF 0x3f3f3f3f
 3 #define LL long long
 4 using namespace std;
 5 const LL mod = 1000000007;
 6 
 7 inline long long multi(long long x,long long y)
 8 {
 9     long long tmp=(x*y-(long long)((long double)x/mod*y+1.0e-8)*mod);
10     return tmp<0 ? tmp+mod : tmp;
11 }
12 
13 
14 LL qpow(LL a, LL n)
15 {
16     LL res = 1;
17     while(n){
18         if(n&1) res = multi(res, a)%mod;
19         a = multi(a, a);
20         n>>=1;
21     }
22     return res%mod;
23 }
24 
25 
26 int main()
27 {
28 //    freopen("result.out", "w", stdout);
29     LL N, p, ans;
30     while(~scanf("%lld", &N)){
31         p = qpow(2, N);
32         ans = (multi((N-1), p)%mod+1)%mod;
33         printf("%lld\n", ans);
34     }
35 
36     return 0;
37 }

 

posted @ 2019-03-17 17:33  莜莫  阅读(694)  评论(0编辑  收藏  举报