題目傳送門
A. Required Remainder
思路
- 題意
- 給我們n,x,y 的值 讓我們找到 k%x==y的k最大值,
- 分析
- 很水的一道題, 考慮n中包含x的數量爲, 我們肯定要把這些包含x全部用上, 纔可以使k更大, 全部用上得到的k爲 ,但是我們要 特殊考慮 如果ct*k+y >n的話要使 答案變成 ct * k + y - x
代碼
#include<iostream>
#include<algorithm>
#include<cstring>
#include<queue>
#include<map>
#include<string>
#include<cstdio>
#include<cmath>
void fre() { freopen("A.txt", "r", stdin); freopen("Ans.txt","w",stdout); }
void Fre() { freopen("A.txt", "r", stdin);}
#define ios ios::sync_with_stdio(false)
#define Pi acos(-1)
#define pb push_back
#define fi first
#define se second
#define ll long long
#define ull unsigned long long
#define db double
#define Pir pair<int, int>
#define PIR pair<Pir, Pir>
#define INF 0x3f3f3f3f
#define mod (ll)(1e9 + 7)
#define for_(i, s, e) for(int i = s; i <= e; i ++)
using namespace std;
const int mxn = 2e5 + 10;
ll ar[mxn];
int main()
{
/* fre(); */
int T;
scanf("%d", &T);
while(T --)
{
int x, y, n;
scanf("%d %d %d", &x, &y, &n);
int t = n / x * x;
int val = t + y;
if(val > n)
val -= x;
printf("%d\n" ,val);
}
return 0;
}
B. Multiply by 2, divide by 6
思路
- 題意
- 給我們一個數n,我們可以對其進行兩種操作:
- 令 n *= 2
- 兩 n /= 6(當 n%6==0的時候)
- 問最少經過多少次 操作 可以把 n 變成1 ?
- 分析
- 首先我們想,如果n一直進行操作2.一直 n除以6的話,最後的結果得到一個1,這是最理想的,最少的操作次數,
- 我們可以把 讓n除6這個操作 看成讓n先除3,在除2, 那麼我們假設n最多可以除以 x個3, 假設 n最多可以除以y個2(求x,y的過程用 因數分解,把n按因子2、3分解 如果最後分解出來剩下的數不是1的話,輸出-1)
- 因爲n實際上除的是6=3*2,所以 n 可以除以x個3,就要求最多隻能被x個連續的2整除,所以如果y > x 的話,我們無論如何 都沒法消去多的次方, 所以輸入-1
- 而如果y < x 的話,我們可以通過 操作1 來增加n中包含2的數量,即:增加y的數量,令y與x 相等,此時x-y就是 要進行1操作的次數, 而x的數量就是 要進行操作2的次數, 兩次數想加就是ans
代碼
#include<iostream>
#include<algorithm>
#include<cstring>
#include<queue>
#include<map>
#include<string>
#include<cstdio>
#include<cmath>
void fre() { freopen("A.txt", "r", stdin); freopen("Ans.txt","w",stdout); }
void Fre() { freopen("A.txt", "r", stdin);}
#define ios ios::sync_with_stdio(false)
#define Pi acos(-1)
#define pb push_back
#define fi first
#define se second
#define ll long long
#define ull unsigned long long
#define db double
#define Pir pair<int, int>
#define PIR pair<Pir, Pir>
#define INF 0x3f3f3f3f
#define mod (ll)(1e9 + 7)
#define for_(i, s, e) for(int i = s; i <= e; i ++)
#define rep_(i, e, s) for(int i = e; i >= s; i --)
using namespace std;
const int mxn = 2e5 + 10;
ll ar[mxn];
int br[5];
int main()
{
/* fre(); */
int T;
scanf("%d", &T);
while(T --)
{
memset(br, 0, sizeof(br));
int n;
scanf("%d", &n);
rep_(i, 3, 2)
{
while(n % i == 0)
{
br[i] ++;
n /= i;
}
}
if(n == 1)
{
if(br[3] < br[2])
printf("-1\n");
else
printf("%d\n", br[3] - br[2] + br[3]);
}
else
printf("-1\n");
}
return 0;
}
C. Move Brackets
思路
- 分析
- 這題沒啥說的,就是 stack 的經典應用題,答案就是 最後還在站內的字符的數量 / 2
代碼
#include<iostream>
#include<algorithm>
#include<cstring>
#include<queue>
#include<map>
#include<string>
#include<cstdio>
#include<cmath>
#include<stack>
void fre() { freopen("A.txt", "r", stdin); freopen("Ans.txt","w",stdout); }
void Fre() { freopen("A.txt", "r", stdin);}
#define ios ios::sync_with_stdio(false)
#define Pi acos(-1)
#define pb push_back
#define fi first
#define se second
#define ll long long
#define ull unsigned long long
#define db double
#define Pir pair<int, int>
#define PIR pair<Pir, Pir>
#define INF 0x3f3f3f3f
#define mod (ll)(1e9 + 7)
#define for_(i, s, e) for(int i = s; i <= e; i ++)
#define rep_(i, e, s) for(int i = e; i >= s; i --)
using namespace std;
const int mxn = 2e2 + 10;
char ar[mxn];
int main()
{
/* fre(); */
int T;
scanf("%d", &T);
while(T --)
{
int n;
scanf("%d", &n);
scanf("%s", ar + 1);
stack<char> st;
for_(i, 1, n)
{
if(st.empty())
st.push(ar[i]);
else
{
if(st.top() == '(' && ar[i] == ')')
st.pop();
else
st.push(ar[i]);
}
}
printf("%lu\n", st.size() / 2);
}
return 0;
}
D. Zero Remainder Array
思路
- 題意
-
給我們一個一個長度爲n 的序列a,現在我們要通過下面兩種操作,使a中所有元素能夠被k整除, 又給我們的一個變量x(初始值爲0)
- 令 ,這個操作 對每個元素a[i]最多隻能使用一次
- 令
-
問我們 最少需要 多少次上面的操作?
- 分析
- 在a中元素中如果已經可以被k整除的話,我們不需要對他們進行操作,我們假設剩下的不能被k整的除的元素的形成的新數組b,對於b中的元素我們求出的每個b中元素距離k某個倍數差了多少,這些差值形成一個新的數組c。
- 舉例:b :{1、1、4、 5} ,k = 3,對於b中每個元素 減去 k 的某個倍數(這個倍數爲)
- 之後得到c:{ 2,2,2,1}–>即:c:{1,2,2,2},
- 對於c中第一個元素1,我們需要先把x從0變爲1(通過操作2),之後再通過一次 操作1 加到第一個元素1上,就是能使c中第一個數對應的在b中的元素可以被k整除了(之後x變爲了1+1=2)
- 接着考慮c中第一個元素2,我需要 2 - x次第一種的操作,和1次第二種的操作,總結一下就是需要(次兩種操作,之後),
- 接下來考慮,這個時候我們發現x=3>2,兩種操作都沒有進行的意義了,這個時候我們只能無奈使的值增大1*k(只要這樣纔可以付出,小的代價,而繼續操作),令c_3+= k == 5,這樣我們需要的進行的次數爲之後x變成了6,
- 當我們進行第四個元素的時候,發現x=6>2,這個時候的我們讓 ,這樣又可以進行操作了
- 核心的過程就是這樣,這個過程的中 特別注意的就是 對於c中重複的元素我們應該 不斷的讓重複的加上 不同的k的倍數 ,之後所有c中的元素就的各不相同了,我們就可以 for循環一遍求出 ans了
代碼
#include<iostream>
#include<algorithm>
#include<cstring>
#include<queue>
#include<map>
#include<string>
#include<cstdio>
#include<cmath>
#include<stack>
void fre() { freopen("A.txt", "r", stdin); freopen("Ans.txt","w",stdout); }
void Fre() { freopen("A.txt", "r", stdin);}
#define ios ios::sync_with_stdio(false)
#define Pi acos(-1)
#define pb push_back
#define fi first
#define se second
#define ll long long
#define ull unsigned long long
#define db double
#define Pir pair<int, int>
#define PIR pair<Pir, Pir>
#define INF 0x3f3f3f3f
#define mod (ll)(1e9 + 7)
#define for_(i, s, e) for(int i = (s); i <= (e); i ++)
#define rep_(i, e, s) for(int i = (e); i >= (s); i --)
using namespace std;
const int mxn = 2e5 + 10;
vector<ll> v;
vector<ll> res;
int main()
{
/* fre(); */
int T;
scanf("%d", &T);
while(T --)
{
v.clear();
res.clear();
ll n, k;
scanf("%lld %lld", &n, &k);
ll t;
for_(i, 1, n)
{
scanf("%lld", &t);
if(t % k)
{
ll ct = t / k;
ll val = k * (ct + 1) - t;
v.pb(val);
}
}
sort(v.begin(), v.end());
pair<ll, ll> p;
p.fi = -1, p.se = 0;
for(int i = 0; i < v.size(); i ++)
{
if(v[i] != p.fi)
{
res.pb(v[i]);
p.fi = v[i];
p.se = 1;
}
else
{
res.pb(v[i] + k * p.se);
p.se ++;
}
}
sort(res.begin(), res.end());
ll sum = 0;
ll x = 0;
for(auto s : res)
{
sum += (s - x + 1);
x = s + 1;
}
printf("%lld\n", sum);
}
return 0;
}
E1. Reading Books (easy version)
思路
- 題意
- 給我們n本書,每本書有三個參數 t、a、b,分別爲:看這本書所需要的時間、a1表示 愛麗絲 喜歡這本書、b1表示 鮑勃 喜歡這本書
- 現在 他們兩個人都要從n本書中選擇k本喜歡的數,他們兩個人選擇的書 形成一個共享的集合(就是兩個人 選擇選擇的書的種類的並集 ),最閱讀的總時間爲這個集合的 沒種書閱讀時間想加,
- 求這個最小時間,如果兩個人都選擇出k本喜歡的書,輸出-1
- 分析
- 這一題根據貪心,首先兩個人選擇的書的總種類越少越好,而且兩個都應該只選k本喜歡的書,不能多選,
- 此外我們可以把:兩本書(一本愛麗絲喜歡,另一本鮑勃喜歡,而且選擇的這兩本書的時間之和儘量小)看做一本新的書,這樣 這本 新讀書 閱讀的總時間就要 原來的兩本書的時間之和,,,這樣我們不斷的選擇兩本書,儘可能的多拼湊出新的書,這本新書兩個人都喜歡
- 這樣,我們 把所有 『拼湊出的書』和 所有原來 就已經被兩個人同時喜歡的書 放在一起形成一個集合 S,從S中選擇k本時間最短的書就是ans(當然如果S中書的數量<k 那麼就是無解,輸出-1)
代碼
#include<iostream>
#include<algorithm>
#include<cstring>
#include<queue>
#include<map>
#include<string>
#include<cstdio>
#include<cmath>
#include<stack>
void fre() { freopen("A.txt", "r", stdin); freopen("Ans.txt","w",stdout); }
void Fre() { freopen("A.txt", "r", stdin);}
#define ios ios::sync_with_stdio(false)
#define Pi acos(-1)
#define pb push_back
#define fi first
#define se second
#define ll long long
#define ull unsigned long long
#define db double
#define Pir pair<int, int>
#define PIR pair<Pir, Pir>
#define INF 0x3f3f3f3f
#define mod (ll)(1e9 + 7)
#define for_(i, s, e) for(int i = (s); i <= (e); i ++)
#define rep_(i, e, s) for(int i = (e); i >= (s); i --)
using namespace std;
const int mxn = 2e5 + 10;
queue<ll> q;
vector<ll> v;
int a[mxn];
int b[mxn];
int main()
{
/* fre(); */
ll n, k;
scanf("%lld %lld", &n, &k);
int t, x, y;
int na = 0, nb = 0;
for_(i, 1, n)
{
scanf("%d %d %d", &t, &x, &y);
if(x == 1 && y == 1)
v.pb(t);
else if(x == 1 && y == 0)
a[na ++] = t;
else if(y == 1 && x == 0)
b[nb ++] = t;
}
sort(a, a + na);
sort(b, b + nb);
/* for_(i, 0, na - 1) */
/* cout << a[i] << " "; */
int ct = min(na, nb);
for_(i, 0, ct - 1)
v.pb(a[i] + b[i]);
if(v.size() >= k)
{
sort(v.begin(), v.end());
int sum = 0;
for_(i, 0, k - 1)
sum += v[i];
printf("%d\n", sum);
}
else
{
printf("-1\n");
}
return 0;
}
剩下題的之後再補。。。。。。。。。。。。