ACM—TC 联合招新赛 Round2
A 贪心
问最少需要多少张纸币可以支付 n元 很容易可以想到 先给100元 100元用完给50 从大到小支付即可。
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <deque>
#include <set>
#include <map>
#include <vector>
using namespace std;
const int INF = 0x3f3f3f3f;
long long n, m, t;
int main()
{
while(~scanf("%lld",&n))
{
long long a,b,c,d;
scanf("%lld %lld %lld %lld",&a,&b,&c,&d);
long long cnt=0;
while(n>0&&a>=1)
{
cnt++;
a--;
n-=100;
}
while(n>0&&b>=1)
{
cnt++;
b--;
n-=50;
}
while(n>0&&c>=1)
{
cnt++;
c--;
n-=20;
}
while(n>0&&d>=1)
{
cnt++;
d--;
n-=10;
}
if(n>0)
{
printf("dangerous!\n");
}
else
{
printf("%lld\n",cnt);
}
}
return 0;
}
B 排序
每个人的总分=高考分×0.85+额外分×0.15
对总分进行从高到低排序 第m名同学的分数 就是 lmw最少要考的分数
lmw的额外分是满分 根据总分计算方程 高考分=(总分-额外分×0.15)/0.85
注意:
1.计算结果可能是小数 高考分数只能是整数 所以要+1
2.总分可能比额外分*0.15小 所以要注意高考分计算结果为负数的情况
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <deque>
#include <set>
#include <map>
#include <vector>
using namespace std;
const int INF = 0x3f3f3f3f;
long long n, m, t;
double ar[100005];
bool cmp(double a,double b)
{
return a>b;
}
int main()
{
long long k;
long long i,j;
long long a,b;
scanf("%lld %lld %lld",&n,&m,&k);
for(i=1;i<=n;i++)
{
scanf("%lld %lld",&a,&b);
ar[i]=a*0.85+b*0.15;
}
sort(ar+1,ar+1+n,cmp);
double sum;
long long ans;
sum=(ar[m]-k*0.15)/0.85;
ans=(ar[m]-k*0.15)/0.85;
if(sum>ans)
{
ans++;
}
if(ans<0)
{
ans=0;
}
printf("%lld",ans);
return 0;
}
C 月黑风高夜,杀人放火天
有n枚铜钱 每次可以取 1~m枚 取走最后一枚的人获胜 问双方都是最佳策略的情况下先手赢还是后手赢
当铜钱有1~m个时,先手一次拿完,先手必胜
当铜钱有m+1个时,先手一次拿不完,但是先手无论拿几个,后手一次都可以拿完,先手必败
当铜钱有m+2~2m+1时,先手可以取特定个数使铜钱剩下m+1个,后手面对m+1必败,先手必胜
以此类推 只有铜钱为m+1的倍数时,后手可以通过取铜钱使先手每次都面临m+1的倍数的情况 必胜,否则 先手可以通过取铜钱使后手每次都面临m+1的倍数 后手必败
具体百度 巴什博弈
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <deque>
#include <set>
#include <map>
#include <vector>
using namespace std;
const int INF = 0x3f3f3f3f;
long long n, m, t;
int main()
{
scanf("%lld",&t);
while(t--)
{
scanf("%lld %lld",&n,&m);
if(n%(m+1)==0)
{
printf("~FuHongXue !~\n");
}
else
{
printf("~YeKai !~\n");
}
}
return 0;
}
D 冲冲冲!是签到题!
算数基本定理
对1~100的每个数字进行分解,最后将每个因子的个数全部相乘即可
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <iostream>
#include <algorithm>
using namespace std;
const int INF=0x3f3f3f3f;
long long n,m,t;
long long mp[1005];
int main()
{
long long ans=1;
long long i,j;
long long x;
for(i=2;i<=100;i++)
{
x=i;
for(j=2;j<=sqrt(x);j++)
{
while(x%j==0)
{
x/=j;
mp[j]++;
}
}
if(x!=1)
{
mp[x]++;
}
}
for(i=1;i<=100;i++)
{
ans=ans*(mp[i]+1);
}
printf("%lld\n",ans);
return 0;
}
E 百年孤独
在文章中找人名 按顺序 一个一个输出就行
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <deque>
#include <set>
#include <map>
#include <vector>
using namespace std;
const int INF = 0x3f3f3f3f;
long long n, m, t;
int main()
{
printf("奥雷连诺\n");
printf("梅尔加德斯\n");
printf("霍·阿·布恩蒂亚\n");
printf("乌苏娜\n");
printf("赫尔曼\n");
return 0;
}
F 抱歉,这位同学,我们的题里没有您做的出的
蛇形矩阵的变形
奇数从左下角开始向右运动
偶数从右上角开始向左运动
i,j表示当前sum所在的矩阵的位置,每次赋值之后移动到下一个点位
奇数从左下角开始 先向右下再向左上依次交替
偶数同理
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <deque>
#include <set>
#include <map>
#include <vector>
using namespace std;
const int INF = 0x3f3f3f3f;
long long n, m, t;
long long mp[1005][1005];
int main()
{
long long i, j;
long long sum;
while (~scanf("%lld", &n))
{
sum = 1;
i = n;
j = 1;
while (sum <= n * n)
{
while (i <= n && j <= n && sum <= n * n)
{
mp[i][j] = sum;
sum += 2;
i++;
j++;
}
i--;
while (i >= 1 && j >= 1 && sum <= n * n)
{
mp[i][j] = sum;
sum += 2;
i--;
j--;
}
j++;
}
i = 1;
j = n;
sum = 2;
while (sum <= n * n)
{
while (i >= 1 && j >= 1 && sum <= n * n)
{
mp[i][j] = sum;
sum += 2;
i--;
j--;
}
i++;
while (i <= n && j <= n && sum <= n * n)
{
mp[i][j] = sum;
sum += 2;
i++;
j++;
}
j--;
}
for (i = 1; i <= n; i++)
{
for (j = 1; j <= n; j++)
{
printf("%5lld", mp[i][j]);
}
cout << endl;
}
cout<<endl;
}
return 0;
}
G 请你喝一杯耗子尾汁
对于矩阵中的每一个数 如果他是他所在行的最小值同时也是他所在列的最大值就输出他行 列以及他的数值
用mi数组储存每一行的最小值
用ma数组储存每一列的最大值
对于矩阵中的每一个数 如果mp[i][j]==mi[i]&&mp[i][j]==ma[j]就是所需的马鞍数
用p进行标记 p=0代表没有找到
如果p=0输出 not exit
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <iostream>
#include <algorithm>
using namespace std;
const int INF=0x3f3f3f3f;
long long n,m,t;
long long mp[105][105];
long long ma[105];
long long mi[105];
int main()
{
memset(mi,INF,sizeof(mi));
scanf("%lld %lld",&n,&m);
long long i,j;
for(i=1;i<=n;i++)
{
for(j=1;j<=m;j++)
{
scanf("%lld",&mp[i][j]);
mi[i]=min(mp[i][j],mi[i]);
ma[j]=max(mp[i][j],ma[j]);
}
}
long long p=0;
for(i=1;i<=n;i++)
{
for(j=1;j<=m;j++)
{
if(mi[i]==ma[j])
{
p=1;
printf("%lld %lld %lld\n",i,j,mp[i][j]);
}
}
}
if(p==0)
{
printf("not exit\n");
}
return 0;
}
H 签到题?真的假的?
玩家初始有100元有n回合 每回合得到ai元,ai可能为负数,玩家可以在任一回合选择终止游戏 判断玩家可以得到的最大钱数
从第一回合开始 向后依次相加
第一回合加第二回合为第二回合得到的钱数
第一回合加第二回合加第三回合为第三回合得到的钱数
对每一回合得到的钱数进行判断 最大值+100即为所求
第一回合也可以不选 所以maxx最小为0
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <iostream>
#include <algorithm>
using namespace std;
const int INF=0x3f3f3f3f;
long long n,m,t;
int main()
{
long long maxx=0;
long long sum=0,x;
scanf("%lld",&t);
while(t--)
{
scanf("%lld",&x);
sum+=x;
maxx=max(maxx,sum);
}
printf("%lld\n",maxx+100);
return 0;
}
I Would you like a drink?
一个游戏
45秒之内为一等奖 奖品 党参
60秒之内为二等奖 奖品 枸杞
90秒之内为三等奖 奖品 保温杯
一个保温杯 两个枸杞 一个党参 可以构成一份茶品
问可以构成多少个
有n个同学参加 每个同学时间为ai
直接算出每个奖品可以得到多少个
计算每个奖品分别可以组成多少份 最少的份数就是最多可以组成的份数
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <iostream>
#include <algorithm>
using namespace std;
const int INF=0x3f3f3f3f;
long long n,m,t;
int main()
{
long long a=0,b=0,c=0;
long long x;
scanf("%lld",&t);
while(t--)
{
a=0,b=0,c=0;
scanf("%lld",&n);
long long i,j;
for(i=1;i<=n;i++)
{
scanf("%lld",&x);
if(x<=45)
{
a++;
}
else if(x<=60)
{
b++;
}
else if(x<=90)
{
c++;
}
}
long long ans=min(c,min(a,b/2));
printf("%lld\n",ans);
}
return 0;
}
J NO GAME NO LIFE
一个单词有多个字迷
可以理解为 两个长度相同的单词 他们拥有的每个字母的个数相同时 可以说一个单词是另一个单词的字迷
题目要寻找 同时是两个以上单词的字迷的字母的个数
用vis标记判断过的地方
vis[i][j]=0代表不是字迷
vis[i][j]=-1代表是特殊单元
vis[i][j]=i表示是第i个的字迷
对于每一个单词:
对于每一行 截取长度与单词长度相同的区间 判断每个字母的个数是否相同 ,相同则吧区间全部标记 对于区间每一个字母 如果被标记为-1则跳过, 如果被标记为i并且i与当前单词的序号不同,则标记为-1 ,ans++;否则标记为当前字母的序号。
对于每一列和左斜线,右斜线同理进行操作。
#include <stdio.h>
#include <map>
#include <stdlib.h>
#include <iostream>
#include <string.h>
#include <algorithm>
using namespace std;
long long n, m, t;
char mp[2005][2005];
long long cn[20005];
long long c1[20005];
long long vis[1005][1005];
char s[50];
int main()
{
long long i, j;
scanf("%lld %lld", &n, &m);
for (i = 0; i < n; i++)
{
scanf("%s", mp[i]);
}
long long k;
scanf("%lld", &k);
long long cnt = 0;
long long x = 0;
long long ans = 0;
long long l = 0;
long long e;
long long p;
long long a, z, b;
for (z = 1; z <= k; z++)
{
for (i = 'A'; i <= 'Z'; i++)
{
c1[i] = 0;
}
scanf("%s", s);
x = strlen(s);
for (i = 0; i < x; i++)
{
c1[s[i]]++;
}
//横
for (i = 0; i < n; i++)
{
for (j = 'A'; j <= 'Z'; j++)
{
cn[j] = 0;
}
cnt = 0;
l = 0;
j = 0;
while (j < m)
{
while (cnt < x && j < m)
{
cn[mp[i][j]]++;
cnt++;
j++;
}
p = 0;
for (a = 'A'; a <= 'Z'; a++)
{
if (cn[a] != c1[a])
{
p = 1;
break;
}
}
if (p == 0)
{
for (a = l; a < j; a++)
{
if (vis[i][a] == 0)
{
vis[i][a] = z;
}
else if (vis[i][a] == -1)
{
continue;
}
else if (vis[i][a] != z)
{
vis[i][a] = -1;
ans++;
}
}
}
cn[mp[i][l]]--;
l++;
cnt--;
}
}
//竖
for (i = 0; i < m; i++)
{
for (j = 'A'; j <= 'Z'; j++)
{
cn[j] = 0;
}
cnt = 0;
l = 0;
j = 0;
while (j < n)
{
while (cnt < x && j < n)
{
cn[mp[j][i]]++;
cnt++;
j++;
}
p = 0;
for (a = 'A'; a <= 'Z'; a++)
{
if (cn[a] != c1[a])
{
p = 1;
break;
}
}
if (p == 0)
{
for (a = l; a < j; a++)
{
if (vis[a][i] == 0)
{
vis[a][i] = z;
}
else if (vis[a][i] == -1)
{
continue;
}
else if (vis[a][i] != z)
{
vis[a][i] = -1;
ans++;
}
}
}
cn[mp[l][i]]--;
l++;
cnt--;
}
}
//右斜
long long x1, y1;
long long p1 ;
long long l1, l2;
long long r1, r2;
x1 = n-1;
y1 = 0;
p1=0;
while (1)
{
l1 = x1;
l2 = y1;
r1 = x1;
r2 = y1;
//cout<<x1<<" "<<y1<<endl;
cnt = 0;
for (j = 'A'; j <= 'Z'; j++)
{
cn[j] = 0;
}
while (r1 < n && r2 < m)
{
while (cnt < x && r1 < n && r2 < m)
{
cn[mp[r1][r2]]++;
cnt++;
r1++;
r2++;
}
p = 0;
for (a = 'A'; a <= 'Z'; a++)
{
if (cn[a] != c1[a])
{
p = 1;
break;
}
}
if (p == 0)
{
for (a = l1, b = l2; a < r1 && b < r2; a++, b++)
{
if (vis[a][b] == 0)
{
vis[a][b] = z;
}
else if (vis[a][b] == -1)
{
continue;
}
else if (vis[a][b] != z)
{
vis[a][b] = -1;
ans++;
}
}
}
cn[mp[l1][l2]]--;
l1++;
l2++;
cnt--;
//cout<<r1<<" "<<r2<<endl;
}
if (p1 == 0)
{
x1--;
if (x1 == -1)
{
x1++;
y1++;
p1 = 1;
}
}
else
{
y1++;
if (y1 >= m)
{
break;
}
}
}
//左斜
x1 = n-1;
y1 = m-1;
p1=0;
while (1)
{
l1 = x1;
l2 = y1;
r1 = x1;
r2 = y1;
//cout<<x1<<" "<<y1<<endl;
cnt = 0;
for (j = 'A'; j <= 'Z'; j++)
{
cn[j] = 0;
}
while (r1 < n && r2>=0)
{
while (cnt < x && r1 < n && r2 >= 0)
{
cn[mp[r1][r2]]++;
cnt++;
r1++;
r2--;
}
p = 0;
for (a = 'A'; a <= 'Z'; a++)
{
if (cn[a] != c1[a])
{
p = 1;
break;
}
}
if (p == 0)
{
for (a = l1, b = l2; a < r1 && b > r2; a++, b--)
{
if (vis[a][b] == 0)
{
vis[a][b] = z;
}
else if (vis[a][b] == -1)
{
continue;
}
else if (vis[a][b] != z)
{
vis[a][b] = -1;
ans++;
}
}
}
cn[mp[l1][l2]]--;
l1++;
l2--;
cnt--;
}
if (p1 == 0)
{
x1--;
if (x1 == -1)
{
x1++;
y1--;
p1 = 1;
}
}
else
{
y1--;
if (y1==-1)
{
break;
}
}
}
}
printf("%lld\n",ans);
return 0;
}