A. Competitive Programmer
题目链接
n组数据,每组数据给一串数字,你可以对这串数字任意排列,问能否得到60的倍数,能的话输出red,否则输出cyan。
数据范围
1
≤
n
≤
148
1\leq n\leq 148
1≤n≤148,
1
≤
∣
s
∣
≤
100
1\leq |s|\leq 100
1≤∣s∣≤100
解 要得到
60
60
60的倍数 即是
10
∗
2
∗
3
10*2*3
10∗2∗3 所以至少要包含一个0放在最后一位 除此以外还要一个偶数放到倒数第二位 然后同时要满足是3的倍数 即各位相加是3的倍数
复杂度
O
(
∣
s
∣
)
O(|s|)
O(∣s∣)
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
void work()
{
char a[105];
scanf("%s",&a);
int l=strlen(a);
bool f1=false;
bool f2=false;
int sum=0;
for(int i=0;i<l;i++){
int k=a[i]-'0';
sum+=k;
if(k>0&&k%2==0||k==0&&f1){
f2=true;
}
if(k==0){
f1=true;
}
}
//printf("%d %d %d\n",sum,f1,f2);
if(sum%3==0&&f1&&f2){
printf("red\n");
}else{
printf("cyan\n");
}
}
int main()
{
ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
int T;
scanf("%d",&T);
//cin>>T;
//T=1;
while(T--){
work();
}
}
B. Dice Tower
题目链接
你可以将多个骰子叠在一起,所获得值为这些骰子漏在外面的面的数值之和,即所有骰子的前后左右4个面和最上面骰子的上面之和,t组数据,每组数据给你一个x,问能否通过任意个骰子组成这个值,可以输出YES,否则输出NO
数据范围
1
≤
t
≤
1000
1\leq t\leq 1000
1≤t≤1000,
1
≤
x
i
≤
1
0
9
1\leq x_i\leq 10^9
1≤xi≤109
解 首先考虑只有一个骰子的时候,即只有一个面删去,最少为
15
15
15。所以少于
15
15
15的情况都不符合。然后在
m
m
m个骰子的情况下,下面
m
−
1
m-1
m−1个骰子,每个骰子必定提供14,第m个骰子提供15-20,所以对
x
%
14
+
14
x\%14+14
x%14+14进行判断即可。
复杂度
O
(
1
)
O(1)
O(1)
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
void work()
{
ll n;
scanf("%lld",&n);
if(n<15){
printf("NO\n");
return;
}
n%=14;
n+=14;
if(n==14||n>20){
printf("NO\n");
}else{
printf("YES\n");
}
}
int main()
{
ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
int T;
scanf("%d",&T);
//cin>>T;
//T=1;
while(T--){
work();
}
}
C. Diverse Matrix
题目链接
给一个矩形的长和宽
r
∗
c
r*c
r∗c,要在每个位置填上一个数,然后要使每行每列的
g
c
d
gcd
gcd各不相同,且最大值最小,输出填入的数。
数据范围
1
≤
r
,
c
≤
500
1\leq r,c\leq 500
1≤r,c≤500
输出要求
a
i
j
≤
1
0
9
a_{ij}\leq 10^9
aij≤109
解 如果
r
=
=
1
&
&
c
=
=
1
r==1\&\&c==1
r==1&&c==1,则无法达到要求 输出0。如果只有一行或者一列,则直接
2
,
3
,
4
,
5
…
…
2,3,4,5……
2,3,4,5……排列即可。取行的
g
c
d
gcd
gcd为
2
,
3
,
4
,
…
…
,
r
+
1
2,3,4,……,r+1
2,3,4,……,r+1,取列的
g
c
d
gcd
gcd为
1
,
r
+
2
,
r
+
3
,
…
…
,
r
+
c
1,r+2,r+3,……,r+c
1,r+2,r+3,……,r+c,
a
i
j
a_{ij}
aij即为第
i
i
i行的
g
c
d
gcd
gcd*第
j
j
j列的
g
c
d
gcd
gcd.
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int a[505][505];
void work()
{
int r,c;
scanf("%d%d",&r,&c);
if(r==1&&c==1){
printf("0\n");
return;
}
if(r==1){
for(int i=1;i<=c;i++){
a[1][i]=i+1;
}
}else if(c==1){
for(int i=1;i<=r;i++){
a[i][1]=i+1;
}
}else{
for(int i=1;i<=c;i++){
a[1][i]=i+1;
}
for(int i=2;i<=r;i++){
for(int j=1;j<=c;j++){
a[i][j]=a[1][j]*(c+i);
}
}
}
for(int i=1;i<=r;i++){
for(int j=1;j<=c;j++){
printf("%d ",a[i][j]);
}
printf("\n");
}
}
int main()
{
ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
int T;
//scanf("%d",&T);
//cin>>T;
T=1;
while(T--){
work();
}
}
D. Decreasing Debts
题目链接
给
n
n
n个人和
m
m
m个关系,每个关系给出
u
i
,
v
i
,
d
i
u_i,v_i,d_i
ui,vi,di,代表
v
v
v欠
u
u
u
d
d
d块钱,如果
b
b
b欠
a
a
a并且
c
c
c欠
b
b
b,那么可以
b
b
b可以将
a
a
a的债务转
m
i
n
(
b
欠
a
,
c
欠
b
)
min(b欠a,c欠b)
min(b欠a,c欠b)给
c
c
c。你可以进行任意次该操作,使得最后每个人债务的总和最少,输出最后的欠债情况。
数据范围
1
≤
n
≤
1
0
5
1\leq n\leq 10^5
1≤n≤105,
0
≤
m
≤
3
∗
1
0
5
0\leq m\leq 3*10^5
0≤m≤3∗105,
1
≤
u
i
,
v
i
≤
n
1\leq u_i,v_i\leq n
1≤ui,vi≤n,
1
≤
d
i
≤
1
0
9
1\leq d_i \leq 10^9
1≤di≤109,
解:要达到最后每个人债务的总和最少,那么必定每个人只有欠债或者只有借贷,如果一个人同时有欠债和借贷,那么明显可以通过操作将其中一个删去,显然是会使债务总和减少。故首先根据读入得出每个人是欠债还是借贷,是多少,分别存入2个vector中,然后取出 一一对应即可。
复杂度
O
(
n
)
O(n)
O(n)
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
struct node
{
int x;
int y;
ll z;
};
vector<int>v1;
vector<int>v2;
ll sum[100005];
void work()
{
int n,m;
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++){
int x,y;
ll z;
scanf("%d%d%lld",&x,&y,&z);
sum[x]-=z;
sum[y]+=z;
}
for(int i=1;i<=n;i++){
if(sum[i]<0){
v1.push_back(i);
sum[i]=-sum[i];
}else if(sum[i]>0){
v2.push_back(i);
}
}
vector<node>ans;
int i=0;
int j=0;
while(i<v1.size()&&j<v2.size()){
int u=v1[i];
int v=v2[j];
node k;
k.x=u;
k.y=v;
k.z=min(sum[u],sum[v]);
ans.push_back(k);
ll tmp=min(sum[u],sum[v]);
sum[u]-=tmp;
sum[v]-=tmp;
if(sum[u]==0)i++;
if(sum[v]==0)j++;
}
printf("%d\n",ans.size());
for(int i=0;i<ans.size();i++){
printf("%d %d %lld\n",ans[i].x,ans[i].y,ans[i].z);
}
}
int main()
{
ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
int T;
//scanf("%d",&T);
//cin>>T;
T=1;
while(T--){
work();
}
}
E. Spaceship Solitaire
题目链接
给
n
n
n种资源,每种资源最少需要
a
i
a_i
ai个,每次你可以获得一份任意一种资源,同时有q个更新,每个更新会给一个三元组
s
,
t
,
u
s,t,u
s,t,u,意思是当第s种资源到达t个时你可以获得一份的u资源,如果u等于0则不添加,如果已经存在s,t的三元组,则先删去原来的三元组,每次更新询问最后达到要求需要多少次。
数据范围
1
≤
n
≤
2
∗
1
0
5
1\leq n\leq 2*10^5
1≤n≤2∗105,
1
≤
a
i
≤
1
0
9
1\leq a_i\leq 10^9
1≤ai≤109,
1
≤
q
≤
1
0
5
1\leq q\leq 10^5
1≤q≤105,
1
≤
s
i
≤
n
1\leq s_i\leq n
1≤si≤n,
1
≤
t
i
≤
a
s
j
1\leq t_i\leq a_{s_j}
1≤ti≤asj,
0
≤
u
j
≤
n
0\leq u_j\leq n
0≤uj≤n
解 因为
t
i
≤
a
s
j
t_i\leq a_{s_j}
ti≤asj,所以免费的
u
i
u_i
ui是必定可以获得的,所以存一下每个资源可以免费获得的量,同时对
s
u
m
sum
sum进行修改,因为如果已经存在
s
,
t
s,t
s,t的三元组就要删去,所以用map存一下
s
,
t
,
u
s,t,u
s,t,u。
复杂度
O
(
q
∗
log
)
O(q*\log)
O(q∗log)
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll a[200005];
struct node
{
int x;
int y;
friend bool operator <(node a,node b){
if(a.x!=b.x)return a.x<b.x;
else return a.y<b.y;
}
};
map<node,int>mp;
ll sum[200005];
void work()
{
int n;
scanf("%d",&n);
ll ans=0;
for(int i=1;i<=n;i++){
scanf("%lld",&a[i]);
ans+=a[i];
}
int q;
scanf("%d",&q);
while(q--){
int s,t,u;
scanf("%d%d%d",&s,&t,&u);
node k;
k.x=s;
k.y=t;
if(mp[k]){
int tmp=mp[k];
sum[tmp]--;
if(sum[tmp]<a[tmp]){
ans++;
}
mp[k]=0;
}
if(u){
sum[u]++;
if(sum[u]<=a[u])ans--;
mp[k]=u;
}
printf("%lld\n",ans);
}
}
int main()
{
ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
int T;
//scanf("%d",&T);
//cin>>T;
T=1;
while(T--){
work();
}
}