hdu 5976 Detachment Inverse element application

Title link: http://acm.hdu.edu.cn/showproblem.php?pid=5976

The problem requires that a number n be decomposed into several different integers, so that their product is the largest. We know that any number x wants to be decomposed into n numbers so that the product is the largest, we must turn each number into x / n The number of limit numbers is divided into three as much as possible, and the rest is divided into two. If the required number cannot be the same, it is necessary to divide the number into consecutive integer segments.

According to past experience, it is necessary to take a continuous natural number to maximize the product, and this continuous natural number can start from 2 (why not start from 1? Starting from 1 is better than giving this 1 to the last number of this continuous natural number) , So we can get a formula of the form 2 + 3 + 4 + ... + k (k = 2,3, ...), and x is any integer within 10 ^ 9, we ca n’t just get together Into a sum of consecutive natural numbers, may be more than △ x

And the value of △ x, I can guarantee that its range is 0≤ △ x≤k, I believe it is greater than or equal to 0 is still understandable, why is it less than or equal to k? Because when it is greater than k, the original formula can not increase by one Term? Ie 2 + 3 + 4 + ... + k + (k + 1)

How to deal with the extra △ x? Obviously, it is evenly distributed to the (k-1) number of consecutive natural numbers from back to front, why from back to front? Because if we go from back to back, we will always make continuous natural numbers Repeat, not easy to handle

Therefore, after we assign △ x, we will roughly get the following two formulas:

①2*3*...*(i-1)*(i+1)*...*k*(k+1)

②3*4*...*i*(i+1)*...*k*(k+2)

Obviously, if we want to calculate this result, we can use factorial, and the missing terms in factorial can be removed, then it will involve division and modulo, obviously need to use multiplicative inverse

The code is as follows: which uses Fermat's little theorem to find the inverse element

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 typedef unsigned int ui;
 4 typedef long long ll;
 5 typedef unsigned long long ull;
 6 #define pf printf
 7 #define mem(a,b) memset(a,b,sizeof(a))
 8 #define prime1 1e9+7
 9 #define prime2 1e9+9
10 #define pi 3.14159265
11 #define lson l,mid,rt<<1
12 #define rson mid+1,r,rt<<1|1
13 #define scand(x) scanf("%llf",&x) 
14 #define f(i,a,b) for(int i=a;i<=b;i++)
15 #define scan(a) scanf("%d",&a)
16 #define mp(a,b) make_pair((a),(b))
17 #define P pair<int,int>
18 #define dbg(args) cout<<#args<<":"<<args<<endl;
19 #define inf 0x7ffffff
20 inline int read(){
21     int ans=0,w=1;
22     char ch=getchar();
23     while(!isdigit(ch)){if(ch=='-')w=-1;ch=getchar();}
24     while(isdigit(ch))ans=(ans<<3)+(ans<<1)+ch-'0',ch=getchar();
25     return ans*w;
26 }
27 int n,m,t;
28 const int maxn=1e5+10;
29 const ll mod = 1e9+7;
30 ll sum[maxn],mul[maxn]; 
31 int top=0;
32ll inv (ll a, int k) // Fermat ’s little theorem solves the inverse element in O (logn) time   
33  {
 34      ll ans = 1 ;
 35      while (k)
 36      {
 37          if (k & 1 ) ans = (ans * a)% mod;
 38          k >> = 1 ;
 39          a = (a * a)% mod;
 40      }
 41      return ans;
 42  }
 43  void init () // Handle prefix sum and prefix product 
44  {
 45      sum [ 1 ] = 1;
 46      mul [ 1 ] = 1 ;
 47      top = 1 ;
 48      ll num = 0 , mu = 1 , i = 2 ;
 49      while (num <= 1000000000 )
 50      {
 51          num = num + i;
 52          sum [++ top ] = num; // accumulate 
53          mu = mu * i% mod;
 54          mul [top] = mu;
 55          i ++ ;
 56      }
 57  }
 58  int main()
59 {
60     //freopen("input.txt","r",stdin);
61     //freopen("output.txt","w",stdout);
62     std::ios::sync_with_stdio(false);
63     init();
64     t=read();
65     while(t--)
66     {
67         n=read();
68         if(n==1)
69         {
70             pf("1\n");
71             continue;
72         }
73          ll ans = 0 ; 
 74          // Find the last position less than or equal to n 
75          int k = upper_bound (sum + 1 , sum + top + 1 , n) -sum- 1 ;
 76          int s = n-sum [k]; / / Remaining number 
77          if (s == k) // This is 3 * 4 ... (k + 1) * (k + 2) form 
78          {
 79              ans = (mul [k] * inv ( 2 , mod- 2 )% mod * (k + 2 ))% mod;
 80           }
 81           else  // This is 2 * 3 * ... * (i-1) * (i + 1) * ... * (k +1) 
82          {
83              ans=(mul[k+1]*inv(mul[k-s+1],mod-2)%mod*mul[k-s])%mod;
84           } 
85         pf("%lld\n",ans);
86     }
87 } 

 

Guess you like

Origin www.cnblogs.com/randy-lo/p/12750478.html