博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【数学、dp】bigcoin 2013广东省赛E题
阅读量:5159 次
发布时间:2019-06-13

本文共 4179 字,大约阅读时间需要 13 分钟。

      比赛现场非常遗憾地没能成功AK的一题,当时最后一个小时已经想到做法,但是交给队友化简公式的时候我竟然非常sb的给错参数了=。=。。。尽管没AK也是冠军但是还是很遗憾啊,算了当给final攒rp吧!!

      题意非常简单,给1、5、100、5000、10000五种硬币,每种数量无限,现在有总价值为n的钱,问如果全部兑换成硬币的话有多少种兑换方案?两个方案如果某一种硬币兑换数量不一样即可以视为不同方案。其中n<=10^18

      如果n比较小的时候这显然可以用背包dp来处理,但是这里n非常大,所以应该利用硬币价值成倍数的特殊条件来设计更快的算法。

算法一:dp。这个是出题者教我的做法,时间复杂度为O(logn)

      对于原问题,我们可以增加一个额外的限制,所有硬币按照价值从大到小依次使用。此时新问题的方案数必然与原问题方案数一样。先假设n是10000的倍数,此时由于所有硬币价值都是10000因子,所以很明显每一个10000的区间都是独立的子问题,即不可能有一个硬币跨越相邻两个10000区间。之后由于我们新增加的限制条件,每一个10000的区间使用的硬币价值都要小于等于上一个区间使用的硬币。于是可以使用dp预处理mat[i][j]表示上一个区间使用最小硬币是i,本区间使用的最小硬币是j,此时区间内放置方案数。之后一共拥有n/10000个这样的区间,我们可以使用矩阵快速加速计算。同理,我们可以把剩下部分提取出大小5000区间,继续使用矩阵乘法计算,等等。

方法二:暴力推导通項。这个是我自己YY出来的,公式推导比较麻烦,但是时间复杂度仅为O(1).

      同样利用所以硬币价值都成倍数关系的特殊条件,如果我们先使用完价值为1的硬币,那么剩下的总价值必然需要是5的倍数。

首先考虑使用价值为1的硬币,令k1=n/5,那么余下价值可能是0,5,10,15...,n/5*5 , 此时每种情况出现方案数均为1,总方案数量设为tol1

之后考虑使用价值为5的硬币,那么余下价值也只可能是0,100,200,。。n/100*100, 此时对于剩余价值为100*i的情形,原先剩余价值已经小于它的方案必定不能取完之后剩余价值变成100*i,故使得这种情形出现的方案数可以用该通項表示  tol1-20i,此时的总方案数量也是可以计算的,设其为tol2。这里我们可以将通项设置A2i+B2方便后续计算。

之后考虑使用价值为100的硬币的时候,余下价值必然是0,5000,10000,。。n/5000*5000。对于剩余价值的为5000i的情形出现的方案数,我们依旧可以使用上诉方法计算第i項其通項为 tol2-∑(A2x+B2) ( 其中 x=0..50i-1),对∑x化简之后可以得到2次的通項A3*i^2+B2*i+C2,此时总方案数依旧可以计算。

最后考虑使用价值为5000的硬币的时候,同理我们可以化简出4次方级别的通項,此时新的总方案数就是原问题的答案,应为最后的剩余价值只有一种处理方法即用10000价值的硬币取尽它。

      最后,在求解通項的时候将其表示成普通多项式的形式,会使得推导下一层通項的时候简单很多。

附代码:

方法一
1 //By Lin 2 #include
3 #include
4 #include
5 #include
6 #include
7 #include
8 #include
9 #include
10 #include
11 #include
12 13 #define eps 1e-914 #define N 10001015 #define sqr(x) ((x)*(x))16 #define Rep(i,n) for(int i = 0; i
pii;25 26 #define MOD 100000000727 const int mm[5] = { 10000,5000,100,5,1};28 LL mat[5][5][5];29 LL dp[10010];30 31 32 LL cal(int L , int l ,int r ){33 if ( mm[r] > L ) return 0;34 memset( dp , 0 , sizeof(dp) );35 dp[0] = 1;36 for(int i = l; i
>=1;62 }63 }64 65 LL A[5][5],B[5][5];66 67 int main(){68 Rep(i,5) Rep(j,5)69 for(int k = j; k<5; k++) {70 mat[i][j][k] = cal(mm[i],j,k);71 }72 int cas;73 LL n;74 scanf("%d", &cas );75 while ( cas -- ) {76 cin >> n;77 LL m = n;78 Rep(i,5) Rep(j,5) A[i][j] = i==j?1:0;79 for(int k = 0; k<5; k++) {80 Rep(i,5) Rep(j,5) B[i][j] = mat[k][i][j];81 quick_sqr(A,B,n/mm[k]);82 n %= mm[k];83 }84 LL ans = 0;85 Rep(j,5) ans = (ans + A[0][j] ) %MOD;86 printf("%lld\n" , ans );87 }88 return 0;89 }
方法二
1 //By Lin 2 #include
3 #include
4 #include
5 #include
6 #include
7 #include
8 #include
9 #include
10 #include
11 #include
12 13 #define eps 1e-914 #define N 10001015 #define sqr(x) ((x)*(x))16 #define Rep(i,n) for(int i = 0; i
pii;25 26 #define MOD 100000000727 28 LL niyuan(LL g){29 LL ret = 1 , h = MOD-2;30 while ( h ) {31 if ( h&1ll ) ret = ret*g%MOD;32 g = g*g%MOD;33 h >>= 1;34 }35 return ret;36 }37 38 LL getsum(int kind , LL K ){39 K %= MOD;40 if ( kind == 0 ) return (K+1)%MOD;41 if ( kind == 1 ) 42 return K*(K+1)%MOD*niyuan(2)%MOD;43 if ( kind == 2 ) 44 return K*(K+1)%MOD*(2*K+1)%MOD*niyuan(6)%MOD;45 if ( kind == 3 ) 46 return K*K%MOD*(K+1)%MOD*(K+1)%MOD*niyuan(4)%MOD;47 }48 49 LL solve4( LL A , LL B, LL C , LL D , LL K ){50 LL tol = getsum(0,K)*D%MOD+getsum(1,K)*C%MOD+getsum(2,K)*B%MOD+getsum(3,K)*A%MOD;51 tol %= MOD;52 return tol;53 }54 LL solve3( LL A , LL B , LL C , LL K ){55 LL tol = getsum(0,K)*C%MOD+getsum(1,K)*B%MOD+getsum(2,K)*A%MOD;56 tol %= MOD;57 LL pA = 16*A%MOD*niyuan(6)%MOD ,58 pB = ((2*B-2*A)%MOD+MOD)%MOD ,59 pC = ((2*A%MOD*niyuan(6)%MOD-B+2*C)%MOD+MOD)%MOD;60 return solve4(MOD-pA,MOD-pB,MOD-pC,tol,K/2);61 }62 LL solve2( LL A , LL B , LL K ){63 LL tol = getsum(0,K)*B%MOD+getsum(1,K)*A%MOD;64 tol %= MOD;65 LL pA = 25*50*A%MOD ,66 pB = ((50*B-25*A)%MOD+MOD)%MOD;67 return solve3(MOD-pA,MOD-pB,tol,K/50);68 }69 LL solve1( LL K ){70 return solve2( MOD-20 , (K+1)%MOD , K/20 );71 }72 73 int main(){74 int cas;75 scanf("%d", &cas );76 while ( cas -- ) {77 LL n;78 cin >> n;79 printf("%lld\n" , solve1(n/5) );80 }81 return 0;82 }

 

转载于:https://www.cnblogs.com/lzqxh/archive/2013/05/13/3076417.html

你可能感兴趣的文章
也谈谈学习
查看>>
针对于多线程概念的理解
查看>>
宿主机为linux、windows分别实现VMware三种方式上网(转)
查看>>
红黑树
查看>>
关于异步的初步认识
查看>>
vue--mixins
查看>>
iOS+HTML5
查看>>
洛谷P1004 方格取数
查看>>
PHP服务器端跨域
查看>>
大白话解析模拟退火算法(转载)
查看>>
虚拟机中3种常见的网络模式
查看>>
三层交换机的设置
查看>>
汇编语言:第九章 转移指令的原理
查看>>
内核的ramdisk
查看>>
Gerrit+apache+H2数据库简单安装配置及建库流程
查看>>
(第三周)团队模式中对交响乐团模式的理解
查看>>
Python2和Python3共存安装robotframework
查看>>
从源代码分析DbSet如何通过ObjectStateManager管理entity lifecycle的生命周期
查看>>
ABAP OO的八大理由(十四)
查看>>
Count Numbers with Unique Digits
查看>>