A. Road To Zero(水题)
- 思路:对两种操作的价格花费进行讨论一下相对大小,不同情况选择不同的方案
代码
#include<vector>
#include<iostream>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<string>
#include<map>
#include<vector>
using namespace std;
void fre() { freopen("A.txt","r",stdin); freopen("Ans.txt","w",stdout); }
#define ll long long
#define INF 0x3f3f3f3f
const int mxn = 3e5;
int main()
{
/* fre(); */
int t;
scanf("%d", &t);
while(t --)
{
ll x, y, a, b;
scanf("%lld %lld %lld %lld", &x, &y, &a, &b);
if(x < y)
swap(x, y);
ll sum = a * (x - y);
if(b > 2*a)
sum += a * 2 * y;
else
sum += b * y;
printf("%lld\n", sum);
}
return 0;
}
B. Binary Period
思路
-
题意
-
分析
代码
#include<vector>
#include<iostream>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<string>
#include<map>
#include<vector>
using namespace std;
void fre() { freopen("A.txt","r",stdin); freopen("Ans.txt","w",stdout); }
#define ll long long
#define INF 0x3f3f3f3f
const int mxn = 3e5;
int main()
{
/* fre(); */
int t;
scanf("%d", &t);
string s;
while(t --)
{
cin >> s;
int flag = 1;
for(int i = 0; i < s.size() - 1; i ++)
{
if(s[i] != s[i+1])
{
flag = 0;
break;
}
}
if(flag)
{
cout << s << endl;
continue;
}
for(int i = 0; i < s.size(); i ++)
cout << "10";
cout << endl;
}
return 0;
}
C. Yet Another Counting Problem(规律+周期)
思路
-
题意: 给我们两个数a,b( ),又给了q次询问,对于每次询问,给我在一个区间 ,让我们在这个区间中找出符合题意的x的数量( )并且 ,求满足这个等式的x的数量
-
分析:分析这一题,当时我在想数据的范围非常大,而且还是询问的次数q也比较多,明显像是规律题,但是题目给的时间 3.5s,说明这并不是一道完全的找规律题,还需要进行一些简单的计算,,,,虽然没做出来但是看到题解的做法是 通过数学中的 周期来简化问题,首先我们先统计出第一个周期 (lcm为最小公倍数,请自己思考第一个周期为什么是我给出的范围)内符合题目中等式的x数量,这样我们在统计有几个周期,就可以解决问题了,具体看代码
代码
#include<vector>
#include<iostream>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<string>
#include<map>
#include<vector>
using namespace std;
void fre() { freopen("A.txt","r",stdin); freopen("Ans.txt","w",stdout); }
#define ll long long
#define INF 0x3f3f3f3f
const int mxn = 3e5;
ll n;
ll gcd(ll a, ll b) { return b == 0 ? a : gcd(b, a%b); }
ll lcm(ll a, ll b) { return a / gcd(a, b) * b; }
ll f[mxn];
ll get_ans(ll x)
{
return 1LL * f[n - 1] * (x/n) + f[x % n];
}
int main()
{
/* fre(); */
int t;
scanf("%d", &t);
while(t --)
{
ll a, b, q;
scanf("%lld %lld %lld", &a, &b, &q);
n = lcm(a, b); //最小公倍数
for(int i = 1; i < n; i ++) //统计在第一个周期[1, n] 中出现的符合题是的数字的数量,i < n是因为 n一定不符合题意所以不用讨论了;
if(i%a%b != i%b%a) f[i] = 1;
else f[i] = 0;
for(int i = 1; i < n; i ++)
f[i] += f[i - 1]; //对当前周期求前缀和
while(q --)
{
ll l, r;
scanf("%lld %lld", &l, &r);
ll ans = get_ans(r) - get_ans(l - 1);
printf("%lld ", ans);
}
printf("\n");
}
return 0;
}
D. Multiple Testcases
思路
-
题意:给我们n个数 ,这数的的范围是 ,又给了k个限制条件 ,对于第i个限制条件表示的意思是:在一个组中元素大于等于i的数要不多于 个;先我们要把这个n个数分成尽可能少的组,而对于分成的每一组都要满足所给的k个限制条件,输出最小分组数量q,并输出每个分组的元素
-
分析:当时自己做的时候觉得很难,但是看完题解之后,并没有什么难的。
- 第一种思路:这中的思路就是从右往左将n个元素依次进行分组,如果 “组”不够了,就添加一个新“组”,接着继续对元素分组,,,分析这种方法,因为从左往右限制条件越来越严格(即: 越来越小),那么我们就先安排后面的数,之后由于越靠前限制条件越来越宽松,我们就可以让靠前的数进行插空,,整个过程的用优先级队列维护空位
- 第二种思路:
- 引入数组 , 表示大于等于i的数字有多少个,之后用当 时用 向上取整,得出每个位置的最小分组数量 ,找出这些最小分组中找出最大的分组数量q,这个q就是我们需要分的最小数量的组数。
- 接下来就是确定每一组中元素分别是啥,我们用贪心的思路去考虑一下,既然最k个位置中最大的分组数量才是q,那么必然 , 表示的意思是大于等于1的元素(其实就是所有元素)最少可以分成 组,那么我们分成更多数量的组q组,那么肯等是可以的,那么有了这个思路之后,那么就是把 n个元素均分成q组,具体看代码
思路1代码
#include<vector>
#include<iostream>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<string>
#include<map>
#include<vector>
#include<queue>
using namespace std;
void fre() { freopen("A.txt","r",stdin); freopen("Ans.txt","w",stdout); }
#define ll long long
#define INF 0x3f3f3f3f
const int mxn = 3e5;
struct Node
{
int cnt;
vector<int> v;
bool operator <(const Node b) const
{
return cnt > b.cnt;
}
Node(){ cnt = 0, v.clear(); }
} st;
int ar[mxn], cr[mxn];
int main()
{
/* fre(); */
int n, k;
scanf("%d %d", &n, &k);
for(int i = 1; i <= n; i ++)
scanf("%d", &ar[i]);
for(int i = 1; i <= k; i ++)
scanf("%d", &cr[i]);
sort(ar + 1, ar + 1 + n);
priority_queue<Node> q;
q.push(st);
for(int i = n; i >= 1; i --)
{
st = q.top(); q.pop();
if(st.cnt < cr[ar[i]])
{
while(i && st.cnt < cr[ar[i]])
{
st.v.push_back(ar[i]);
st.cnt ++;
i --;
}
i ++;
q.push(st);
}
else
{
Node ed;
q.push(ed);
q.push(st);
i ++;
}
}
printf("%lu\n", q.size());
while(! q.empty())
{
st = q.top(); q.pop();
printf("%d", st.cnt);
for(auto x : st.v)
printf(" %d", x);
printf("\n");
}
return 0;
}
思路2代码
#include<vector>
#include<iostream>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<string>
#include<map>
#include<vector>
using namespace std;
void fre() { freopen("A.txt","r",stdin); freopen("Ans.txt","w",stdout); }
#define ll long long
#define INF 0x3f3f3f3f
const int mxn = 3e5;
int ar[mxn], br[mxn], cr[mxn]; //ar存放原始数据,br[i]存放大于等i所有元素数量,即后缀数组,cr存限制条件
vector<int> res[mxn];
int main()
{
/* fre(); */
int n, k;
scanf("%d %d", &n, &k);
for(int i = 0; i < n; i ++)
{
scanf("%d", &ar[i]);
br[ar[i]] ++;
}
for(int i = 1; i <= k; i ++)
scanf("%d", &cr[i]);
int q = 0; //分组数量
for(int i = k; i >= 1; i --)
{
br[i] += br[i + 1];
q = max(q, (int)ceil((double)br[i]/cr[i]));
}
sort(ar, ar + n);
for(int i = 0; i < n; i ++)
res[i%q].push_back(ar[i]);
printf("%d\n", q);
for(int i = 0; i < q; i ++)
{
printf("%d ",res[i].size());
for(auto x : res[i])
printf("%d ", x);
printf("\n");
}
return 0;
}
转载:https://blog.csdn.net/qq_34261446/article/details/105800914
查看评论