首页 > 代码库 > hdu--5139--bc

hdu--5139--bc

这题 很多人用的都是 离线处理的方法。

比赛的时候 就没想到这个方法。

一直在mle tle之间徘徊。。 porker的这个处理数组方法很好

我本来是1-1e7的数组范围存下的是每个f[n]的值

现在我用一个 1-1e6的数组来表示f[n] , g[n]            g[n]就是n的阶乘

因为 f[n] = f[n-1] * g[n]

那么当我的数组范围是开到1e6的时候 就是说0存的是n=1的解 1存的是n=10的解 10 存的是n=100的解 11存的是n=110的解

那么你可以发现 我任意一个要查询的数n 都将落在[n/10,n/10+1)这个区间内的某个数之内 就是说15会在[1,2)之间

45会在[4,5)之内。

这种方法不仅适用于本题 对于某些对内存要求很高的 同时你的方法足够满足这个时间的情况下 可以这样来解决

同时 这边你的数组最好开成int来计算 虽然当我们进行上面步骤之后 也不会mle  但是为了保险开成int来保存

但是 中途计算的时候 会爆 int所以我们需要先转换为LL 最后计算完成之后在强制转换为int

ok 贴下代码 离线的明天再贴 打游戏啦。。

 1 #include <iostream> 2 using namespace std; 3  4 typedef __int64 LL; 5 const int size = 10000010; 6 const int mod = 1000000007; 7 LL n; 8 int f[1000010]; 9 int g[1000010];10 11 void init( )12 {13     f[0] = g[0] = 1;14     int now , next;15     now = 1;16     int sum , ans;17     sum = 1;18     for( int i = 2 ; i<=size-9 ; i++ )19     {20         next = (int)( ( 1LL * ( now%mod ) * i ) % mod);21         ans = (int)( ( 1LL * (sum%mod) * (next%mod) ) % mod);22         now = next;23         sum = ans;24         if( i%10==0 )25            {26            f[i/10] = ans;27               g[i/10] = next;    28         }29     }30 }31 32 int main()33 {34     init( );35     LL temp , sum , ans , now , next;36     while( ~scanf("%d",&n) )37     {38         if( n%10==0 )39         {40             printf( "%d\n",f[n/10] );41         }42         else43         {44             temp = n/10;45             ans = 1LL * f[n/10];46             sum = ans;47             now = 1LL * g[n/10];48             for(  LL i = temp*10+1 ; i<=n ; i++ )49             {50                 next = (int)( ( now%mod ) * i % mod );51                 ans = (int)(  (sum%mod) * (next%mod) % mod );52                 now = next;53                 sum = ans;54             }55             printf( "%I64d\n",ans);56         }57     }58     return 0;59 }
View Code

 

hdu--5139--bc