题目来自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
