题目来自TopCoder
MonstersValley
#include<vector> #include<iostream> using namespace std; class MonstersValley2{ public: int minimumPrice(vector <int> dread,vector <int> price){ long long dp[21][41]; for(int i=0;i<=40;i++)dp[0][i]=0; for(int i=1;i<=dread.size();i++){ for(int j=0;j<=40;j++){ dp[i][j]=-1; if(dp[i-1][j]>=dread[i-1])dp[i][j]=dp[i-1][j]; if(j>=price[i-1]&&dp[i-1][j-price[i-1]]!=-1){ long long t=dp[i-1][j-price[i-1]]+dread[i-1]; if(t>dp[i][j])dp[i][j]=t; } cout<<dp[i][j]<<' '; } cout<<endl; } for(int j=0;j<=40;j++){ if(dp[dread.size()][j]!=-1)return j; } return -1; } };
DivisibleSequence
生成单调序列的方法:
质因数分解的试除法:
// Let us use trial divison to find prime factors p for (int p=2; p <= N/p; p++) { int c = 0; while (N % p == 0) { N /= p; c++; } res = ( res * C(H-1+c, c) ) % MOD; } if (N > 1) { // N is one last prime factor, c = 1 // C(H-1+1,1) = H res = ( res * H ) % MOD; }
注意大于sqrt(N)的质因子最多只有一个,所以最后只要检测N是否大于1,如果大于1的话N就是最后的质因数。
计算C(n,k)的方法:
官方题解提供的代码
final int MOD = 1000000009; // Calculates x raised to the y-th power modulo MOD long modPow(long x, long y) { long r=1, a=x; while (y > 0) { if ( (y&1)==1 ) { r = (r * a) % MOD; } a = (a * a) % MOD; y /= 2; } return r; } // Modular multiplicative inverse through Fermat's little theorem: long modInverse(long x) { return modPow(x, MOD-2); } // Modular division x / y, find modular multiplicative inverse of y // and multiply by x. long modDivision(long p, long q) { return (p * modInverse(q)) % MOD; } // Binomial coifficient C(n,k) in O(k) time. long C(long n, int k) { if (k > n) { return 0; } long p = 1, q = 1; for (int i=1; i<=k; i++) { q = ( q * i) % MOD; p = ( p * (n - i + 1) ) % MOD; } return modDivision( p, q); }
这里出现了modular division,Modular multiplicative inverse(模反元素)的概念 和 费马小定理(Fermat's little theorem)
如果a-1和x对于m是同模的,则x就是a的模反元素,这时有a*x mod m = a*a-1 mod m = 1
模反元素可以用于计算modular division,p/q mod m 可以表示为 p*q-1 mod m,其中q-1是q的模反元素。
而费马小定理可以方便地解决m为素数时求解q-1的问题:
假如a是一个整数,p是一个质数,这个定理表明ap mod p = a mod p
如果a不是p的倍数,这个定理可以写成ap-1mod p = 1。
如此以来,对于本题我们只要计算ap-2即为a的模反元素。
怎样计算xy :
观察官方题解的modPow函数,这个方法巧妙地用o(log(y))的时间计算了xy 。
代码维护了底数a和结果r。初始时r=1,a=x,每一步迭代中如果y是奇数,则r更新为r*a。然后底数a更新为a2,指数y更新为y/2。
这是因为xy=(x2)y/2*xy%2 ,这样计算xy就转化为计算(x2)y/2