1. 小易為了向他的父母表現他已經長大獨立了,他決定搬出去自己居住一段時間。一個人生活增加了許多花費: 小易每天必須吃一個水果並且需要每天支付x元的房屋租金。當前小易手中已經有f個水果和d元錢,小易也能去商店購買一些水果,商店每個水果售賣p元。小易為了表現他獨立生活的能力,希望能獨立生活的時間越長越好,小易希望你來幫他計算一下他最多能獨立生活多少天。
輸入描述:
輸入包括一行,四個整數x, f, d, p(1 ≤ x,f,d,p ≤ 2 * 10^9),以空格分割
輸出描述:
輸出一個整數, 表示小易最多能獨立生活多少天。
輸入例子1:
3 5 100 10
輸出例子1:
11
C++代碼如下:
#include<iostream>
using namespace std;
int main(){
int x, f, d, p;
cin >> x >> f >> d >> p;
int tmp1 = d / x;
if(tmp1 <= f){
cout<<tmp1;
return 0;
}
d=d-(f*x);
int tmp2=d/(x+p);
cout<<f+tmp2;
return 0;
}
2. 小易將n個棋子擺放在一張無限大的棋盤上。第i個棋子放在第x[i]行y[i]列。同一個格子允許放置多個棋子。每一次操作小易可以把一個棋子拿起並將其移動到原格子的上、下、左、右的任意一個格子中。小易想知道要讓棋盤上出現有一個格子中至少有i(1 ≤ i ≤ n)個棋子所需要的最少操作次數.
輸入描述:
輸入包括三行,第一行一個整數n(1 ≤ n ≤ 50),表示棋子的個數 第二行為n個棋子的橫坐標x[i](1 ≤ x[i] ≤ 10^9) 第三行為n個棋子的縱坐標y[i](1 ≤ y[i] ≤ 10^9)
輸出描述:
輸出n個整數,第i個表示棋盤上有一個格子至少有i個棋子所需要的操作數,以空格分割。行末無空格 如樣例所示: 對於1個棋子: 不需要操作 對於2個棋子: 將前兩個棋子放在(1, 1)中 對於3個棋子: 將前三個棋子放在(2, 1)中 對於4個棋子: 將所有棋子都放在(3, 1)中
輸入例子1:
4 1 2 4 9 1 1 1 1
輸出例子1:
0 1 3 10
思路:對於一個k,我們找一個坐標(x, y)讓k個棋子距離這個坐標的曼哈頓距離之和最小。
注意到x和y其實是獨立的,考慮枚舉棋盤上所有可能得坐標(x[i], y[j]),計算這個坐標到所有棋子的距離分別是多少,
然后維護k個棋子對於這個坐標最小曼哈頓距離和即可。
C++代碼如下:
#include <bits/stdc++.h>
using namespace std;
const int inf = 1e9;
int main() {
int n;
cin >> n;
vector<int> x;
vector<int> y;
int x_num;
int y_num;
for(int i = 0; i < n; i++){
cin >> x_num;
x.push_back(x_num);
}
for(int i = 0; i < n; i++){
cin >> y_num;
y.push_back(y_num);
}
vector<int> res(n, inf);//初始化為很大的數;
//i表示存放最終的結果的下表;
for(int i = 0; i < n; i++) {
//j,k代表遍歷網格的坐標;
for(int j = 0; j < n; j++) {
for(int k = 0; k < n; k++) {
vector<int> res2(n);
//l代表每一個棋子所在的坐標;
for(int l = 0; l < n; l++) {
res2[l] = abs(x[l] - x[j]) + abs(y[l] - y[k]);
}
sort(res2.begin(), res2.end());
int res3 = 0;
for(int l = 0; l < i + 1; l++) res3 += res2[l];
res[i] = min(res[i], res3);
}
}
}
for(int i = 0; i < n; i++) {
//輸出格式控制;
i == 0 ? cout << res[i] : cout << " " << res[i];
}
return 0;
}
3. 小易非常喜歡擁有以下性質的數列:
1、數列的長度為n
2、數列中的每個數都在1到k之間(包括1和k)
3、對於位置相鄰的兩個數A和B(A在B前),都滿足(A <= B)或(A mod B != 0)(滿足其一即可)
例如,當n = 4, k = 7
那么{1,7,7,2},它的長度是4,所有數字也在1到7范圍內,並且滿足第三條性質,所以小易是喜歡這個數列的
但是小易不喜歡{4,4,4,2}這個數列。小易給出n和k,希望你能幫他求出有多少個是他會喜歡的數列。
輸入描述:
輸入包括兩個整數n和k(1 ≤ n ≤ 10, 1 ≤ k ≤ 10^5)
輸出描述:
輸出一個整數,即滿足要求的數列個數,因為答案可能很大,輸出對1,000,000,007取模的結果。
輸入例子1:
2 2
輸出例子1:
3
思路:想象一下,如果我們確定這個數列的第一個數是i,那么第二個數可以是1到k中除了是i的約數的任何數。
於是我們定義dp[j][i]表示長度為i最后一個數是j的小易喜歡的數列的數量,然后挨着轉移即可。用動態規划的方法;
C++代碼如下:
#include <bits/stdc++.h>
using namespace std;
const int mod = 1e9 + 7;
const int maxn = 1e5 + 5;
int dp[maxn][15];
int n, k;
int main() {
cin >> n >> k;
dp[1][0] = 1;
for(int i = 1; i <= n; i++) {
int sum = 0;
for(int j = 1; j <= k; j++) {
sum += dp[j][i - 1];
sum %= mod;
}
for(int j = 1; j <= k; j++) {
int sum2 = 0;
for(int z = j + j; z <= k; z += j) {
sum2 += dp[z][i - 1];
sum2 %= mod;
}
dp[j][i] = (sum - sum2 + mod) % mod;
}
}
int ans = 0;
for(int j = 1; j <= k; j++) {
ans += dp[j][n];
ans %= mod;
}
cout << ans << endl;
return 0;
}
總結:
第一個題目很簡單,但是沒有完全AC,一定要仔細思考,多嘗試案例,找到漏洞;
第二個題目,關於題目的意思沒有理解清楚,最初擔心復雜度的問題,到最后看到解法,其實就是用遍歷。所以先寫出一個可以運行的代碼,復雜度后面再說;
第三個題目是動態規划的問題,練得太少了,還沒想出思路來,對動態規划要更加熟悉。
