A:
Anastasia and pebbles
题意:
有两个口袋,每个口袋的能装k个鹅卵石, 且只能装同一种鹅卵石,给定不同类型的鹅卵石的个数,每一天用这两个口袋去装鹅卵石, 问:最少几天能将所有的鹅卵石带走
求解:
求出不同种类的所有的鹅卵石总共需要几个口袋, 然后总口袋数/2即可(注意,口袋可以不用装满,但必须是同一个类型的鹅卵石)
Code:
B.
Masha and geometric depression
题意:
给出一个等比数列的b1和q, 则 bn=bn-1 * q; 求在 |bn|<=L以及bn不能出现在给出的Bad数组中的条件下, 共有多少个数bn, 可以重复, 且允许b=q=0;若无穷个,则输出inf,否则输出个数
求解:
对b=0,q=0, q=+1,q=-1进行特判, 因为这几种情况可能产生inf, 其他情况不会。对于其他情况,直接求出从b1到
|bn|<=L总共有几个数, 其中满足条件但是在Bad数组中出现的不计算在内。
Code:
C.
Functions again
题意:
给定一组数据,(顺序不可变),根据上述公式求出f的最大值.
求解:
先将|a[i]-a[i+1]|的序列p求出来, 根据f方程式
容易知道, 总共只有两种情况,
1. p中下标为奇数的数*-1, p中下标为偶数的数*1;
2. p中下标为奇数的数*1, p中下标为偶数的数*-1;
故只需要进行两次遍历数组, 并采用最大连续和的算法解决. 注意此题数据较大,应开long long 或者 __int64
Code:
D:
Weird journey
题意:
求是否有一条路径可以经过所有的道路, 且有m-2道路被经过两次, 其余2条道路只经过一次。(城市与城市之间的道路, 以及城市与本身的自环道路), 输出满足条件的路径的数目
求解:
先确定是否有一条路径可以满足条件, 只需判断是否所有的道路都是互通的
然后, 分析可知, 只经过一次的两条道路的可能情况如下:
1.两条道路均为自环道路
2.一条为自环道路, 另一条为不同城市之间的道路
3.两条均为 不同城市之间的道路(注意:这两条道路必须是相邻的, 否则无法满足条件)
Code:
求出不同种类的所有的鹅卵石总共需要几个口袋, 然后总口袋数/2即可(注意,口袋可以不用装满,但必须是同一个类型的鹅卵石)
Code:
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<string>
#include<queue>
#include<stack>
using namespace std;
const int maxn = 100005;
int num[maxn];
bool cmp(int a, int b){
return a>b;
}
int main()
{
int n, k=0;
int sum=0;
scanf("%d %d", &n, &k);
for(int i=1; i<=n; i++){
scanf("%d", &num[i]);
sum += num[i]/k;
if(num[i] - (num[i]/k*k)>0) sum++;
}
printf("%d\n", (sum+1)/2);
return 0;
}
B.
Masha and geometric depression
题意:
给出一个等比数列的b1和q, 则 bn=bn-1 * q; 求在 |bn|<=L以及bn不能出现在给出的Bad数组中的条件下, 共有多少个数bn, 可以重复, 且允许b=q=0;若无穷个,则输出inf,否则输出个数
求解:
对b=0,q=0, q=+1,q=-1进行特判, 因为这几种情况可能产生inf, 其他情况不会。对于其他情况,直接求出从b1到
|bn|<=L总共有几个数, 其中满足条件但是在Bad数组中出现的不计算在内。
Code:
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<string>
#include<queue>
#include<stack>
#include<cmath>
using namespace std;
const int maxn = 100005;
int num[maxn];
__int64 b, q, l, m;
int main()
{
scanf("%I64d %I64d %I64d %I64d", &b, &q, &l, &m);
int i;
for(i=1; i<=m; i++){
scanf("%d", &num[i]);
}
sort(num+1, num+1+m);
if(abs(b) > l) printf("0\n");
else if(q==1||q==-1 || q==0 || b==0) {
if(q==1 ){
int pos = lower_bound(num+1, num+m+1, b)-num;
if(pos>m || num[pos]!= b) printf("inf\n");
else printf("0\n");
} else if(q==-1 ){
int pos = lower_bound(num+1, num+m+1, b)-num;
int pos2 = lower_bound(num+1, num+m+1, -b)-num;
int p=0;
if(pos>m || num[pos]!=b || pos2>m || num[pos2]!=-b){
printf("inf\n");
} else {
printf("0\n");
}
} else if(q==0){
int pos = lower_bound(num+1, num+m+1, 0)-num;
if(pos>m || num[pos]!=0) printf("inf\n");
else {
int pos2 = lower_bound(num+1, num+m+1, b)-num;
if(pos2>m || num[pos2]!=b) printf("1\n");
else printf("0\n");
}
} else if(b==0){
int pos = lower_bound(num+1, num+m+1, 0)-num;
if(pos>m || num[pos]!=0) printf("inf\n");
else printf("0\n");
}
}
else {
__int64 n=0;
__int64 u = b;
while(abs(u)<=l){
int pos = lower_bound(num+1, num+m+1, u)-num;
if(pos>m || num[pos]!=u ) n++;
u*=q;
if(u==b)break;
}
printf("%I64d\n", n);
}
return 0;
}
C.
Functions again
题意:
![](https://i-blog.csdnimg.cn/blog_migrate/21407b8feb2eae9c446672c34e0b0f5d.png)
求解:
先将|a[i]-a[i+1]|的序列p求出来, 根据f方程式
容易知道, 总共只有两种情况,
1. p中下标为奇数的数*-1, p中下标为偶数的数*1;
2. p中下标为奇数的数*1, p中下标为偶数的数*-1;
故只需要进行两次遍历数组, 并采用最大连续和的算法解决. 注意此题数据较大,应开long long 或者 __int64
Code:
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<string>
#include<queue>
#include<stack>
using namespace std;
const int maxn = 100005;
__int64 num[maxn];
int main()
{
__int64 n;
scanf("%I64d", &n);
__int64 x, y, len=0;
for(int i=1; i<=n; i++){
scanf("%I64d", &x);
if(i==1) y=x;
else {
num[len++] = abs(y-x);
y=x;
}
}
__int64 p = 1;
__int64 sum=0;
__int64 MAX = -1;
for(__int64 i=0; i<len; i++){
if(i%2==0) p=1;
else p=-1;
sum += p*num[i];
if(sum>MAX){
MAX = sum;
}
if(sum<0) sum=0;
}
sum = 0;
for(__int64 i=0; i<len; i++){
if(i%2!=0) p=1;
else p=-1;
sum += p*num[i];
if(sum>MAX){
MAX = sum;
}
if(sum<0) sum=0;
}
printf("%I64d\n", MAX);
return 0;
}
D:
Weird journey
题意:
求是否有一条路径可以经过所有的道路, 且有m-2道路被经过两次, 其余2条道路只经过一次。(城市与城市之间的道路, 以及城市与本身的自环道路), 输出满足条件的路径的数目
求解:
先确定是否有一条路径可以满足条件, 只需判断是否所有的道路都是互通的
然后, 分析可知, 只经过一次的两条道路的可能情况如下:
1.两条道路均为自环道路
2.一条为自环道路, 另一条为不同城市之间的道路
3.两条均为 不同城市之间的道路(注意:这两条道路必须是相邻的, 否则无法满足条件)
Code:
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<vector>
using namespace std;
typedef __int64 (ll);
const int maxn = 1e6+50;
int fa[maxn], u[maxn], v[maxn];
bool vis[maxn];
ll flag[maxn];
ll d[maxn];
ll find(int x){
if(fa[x]==x) return x;
else return (fa[x]=find(fa[x]));
}
void Unit(int a, int b){
int f1 = find(a);
int f2 = find(b);
if(f1!=f2) fa[f1]=f2;
return ;
}
int main()
{
int i, j, a, b, len=0;
ll n, m, cnt1=0, cnt2=0;
memset(d, 0, sizeof(d));
memset(vis, 0, sizeof(vis));
scanf("%I64d %I64d", &n, &m);
for(i=1; i<=n; i++) fa[i]=i;
for(i=1; i<=m; i++){
scanf("%d %d", &a, &b);
u[i]=a,v[i]=b;
if(a==b) cnt1++;
else{
d[a]++;
d[b]++;
cnt2++;
Unit(a, b);
}
}
int em = find(u[1]);
bool flag=true;
//判断所有的边是否都互通
for(i=2; i<=m; i++) {
int f;
if(!vis[u[i]]) f=find(u[i]);
if(find(!vis[v[i]])) f=find(v[i]);
vis[u[i]] = vis[v[i]] = 1;
f=find(u[i]);
if(f!=em){
flag=false;
break;
}
}
if(!flag){
printf("0\n");
} else {
ll ans=0;
ans += cnt1*cnt2;//自环边与非自环边
ans += cnt1*(cnt1-1)/2;//自环边与自环边
for(i=1; i<=n; i++)//非自环边与非自环边
{
ans += d[i]*(d[i]-1)/2;
}
printf("%I64d\n", ans);
}
}