A、最大公倍数
是一个结论题吧。
当
是奇数的时候,那么答案肯定是
,因为他们两两互质。
然后当
时,直接求一个lcm。
否则就是偶数:偶数的话如果是3的倍数,答案就是
,否则b-1,就变成奇数的情况了。
class Solution {
public:
/**
* @param a: Left margin
* @param b: Right margin
* @return: return the greatest common multiple
*/
#define ll long long
template<typename T>T gcd(T a, T b) {return b==0?a:gcd(b, a%b);}
template<typename T>T exgcd(T a,T b,T &g,T &x,T &y){if(!b){g = a,x = 1,y = 0;}
else {exgcd(b,a%b,g,y,x);y -= x*(a/b);}}
ll greatestcommonmultiple(int a, int b) {
// write your code here
ll res = 0;
if(b&1)res = 1ll*b*(b-1)*(b-2);
else if(b-a==2){
res = lcm(b,lcm(b-1,b-2));
}else{
if(b%3!=0)res = 1ll*b*(b-1)*(b-3);
else res = 1ll*(b-1)*(b-2)*(b-3);
}
return res;
}
ll lcm(int a,int b){
return 1ll*a*b/gcd(a,b);
}
};
B、房屋染色
定义
表示以
结尾颜色为
且是否已有步行街的最小代价
。
然后维护一个前缀和,那么转移就是
只移动一步。
有步行街。
class Solution {
public:
/**
* @param costs: costs of paint ith house into color j
* @param t: maximum length of street
* @return: minimum costs of painting all houses
*/
long long va[105][105];
long long dp[105][105][2];
int paintHouseIII(vector<vector<int>> &costs, int t) {
// Write your code here.
int n = costs.size(),m = costs[0].size();
for(int i = 0;i < m;++i){
for(int j = 0;j < n;++j){
if(j==0)va[j][i] = costs[j][i];
else va[j][i] = va[j-1][i] + costs[j][i];
// cout<<j<<" "<<i<<" " << va[j][i]<<endl;
dp[j][i][0] = dp[j][i][1] = INT_MAX;
}
}
for(int i = 0;i < m;++i)dp[0][i][0] = dp[0][i][1] = costs[0][i];
for(int i = 0;i < n;++i){
for(int j = 0;j < m;++j){
for(int k = 0;k < m;++k){
if(j==k){
for(int p = 0;p < t;++p){
if(i+p>=n)break;
dp[i+p][k][1] = min(dp[i+p][k][1],dp[i][k][0]+va[i+p][k]-va[i][k]);
}
continue;
}
if(i+1<n){
dp[i+1][k][0] = min(dp[i+1][k][0],dp[i][j][0]+costs[i+1][k]);
dp[i+1][k][1] = min(dp[i+1][k][1],dp[i][j][1]+costs[i+1][k]);
}
}
}
}
long long res = INT_MAX;
for(int i = 0;i < m;++i)res = min(res,min(dp[n-1][i][1],dp[n-1][i][0]));
return res;
}
};
字符串游戏
抽象为 逆Nim 博弈
Nim 博弈:两个人玩游戏,有 n 堆石子,每次操作可以选一堆石子xjb拿,最少拿一颗,无子可取者为负。
class Solution {
public:
/**
* @param s: a string for this game
* @return: return whether Alice can win this game
*/
bool stringGame(string &s) {
// Write your code here.
int num[30] = {0};
for(int i = 0;i < s.size();++i){
num[s[i]-'a']++;
}
int res = 0;
bool f= 1,f1 = 0;
for(int i = 0;i < 26;++i){
if(!num[i])continue;
res ^= num[i];
if(num[i]!=1)f = 0;
if(num[i]>1)f1 = 1;
}
if(f&&!res||f1&&res)return true;
else return false;
}
};
完美字符串
直接选取连续的0,然后最大限度的翻转它就ok了,即当有连续5个0,k=3,那么需要翻转2次。
class Solution {
public:
/**
* @param s: string need to be transformed
* @param k: minimum char can be transformed in one operation
* @return: minimum times of transforming all char into '1'
*/
int perfectString(string &s, int k) {
long long res = 0;
int i = 0,len,j;
while(i < s.size()){
if('1'==s[i]){i++;continue;}
j = i;
while(j<s.size()&&s[j]=='0')++j;
len = j-i;
res += len/k;
if(len%k)res++;
i = j;
}
return res;
}
}a;