场次链接
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();
}
}