第二次参加图森杯了,去年A了三题,今年有六题,不错不错……
比赛题目一览:
A:Thanks, TuSimple!
B: Even Number Theory
C:Robot Cleaner I
D:Robot Cleaner II
E:Potion
F:Strange Function
G:Postman
H: Rescue the Princess
I:Defense Plan
J:Extended Twin Composite Number
比赛一开始,就有人切掉了J题,噢,一定是大水题啊!
J题讲的是给你一个整数n,让你随便找一组整数解x,y,使得x+n=y,而且x和y都是合数
沉默……
“哦,这岂不是很简单吗!如果n是偶数,那就随便找两个差4的偶数不就好了,如果n是奇数,那就找个9和9+n就行了,9+n一定是偶数,如此之简单”
AC!
#include
using namespace std;
int main(){
int cas;
scanf("%d",&cas);
while(cas--){
long long n;
scanf("%lld",&n);
if (n%2==0) printf("4 %lld\n",4+n);
else printf("9 %lld\n",9+n);
}
return 0;
}
看下ranklist,发现可以做E题
嗯,这题什么意思?
什么,降级?魔药?……(←论英语的重要性)
……
在百般挣扎后终于看懂了题目,按等级给你一堆材料的需求量,再按等级给出你有多少材料,你所拥有的材料是可以降级的,将级没有限制,降几级,降几次都可以,然后问你材料够不够
呵呵,那不就是一道水题吗?从后往前扫,多出来的能降级就降级,一单不够了就条出
WA!!!
哦哦哦,long long
AC!!!
#include
using namespace std;
const int maxn=105;
long long a[maxn],b[maxn];
int main(){
int cas;
scanf("%d",&cas);
while(cas--){
int n,flag=0;
scanf("%d",&n);
for (int i=1;i<=n;i++){
scanf("%lld",&a[i]);
}
for (int i=1;i<=n;i++){
scanf("%lld",&b[i]);
}
for (int i=n;i>=1;i--){
if (a[i]>b[i]){
printf("No\n");
flag=1;
break;
}
else{
b[i-1]+=b[i]-a[i];
}
}
if (!flag) printf("Yes\n");
}
return 0;
}
接着就是G题了:
题目意思很简单:就是再一个数轴上,原点是邮局,每次到邮局可以拿不超过k封信,给出需要送信的坐标,问最少要跑多远
好吧,又是水题,到了原点我们的信就可以加满了,So,正负半轴我们完全可以分开讨论
显然每一次我送的k封信一定是连续的,那我们就把这些点每k个分成一段,那么每一段的代价都是从远点到这一段最远那个点的距离*2,由于最后一次只去无回(←听上去怪怪的),So,我们把到原点距离最远的减掉一个(正负半轴只能减一个),完事
#include
using namespace std;
int n,k;
vector<int> a,b;
int main(){
int cas;
scanf("%d",&cas);
while(cas--){
long long ans=0;
a.clear();
b.clear();
scanf("%d%d",&n,&k);
for (int i=1;i<=n;i++){
int tmp;
scanf("%d",&tmp);
if (tmp==0) continue;
if (tmp>0) a.push_back(tmp);
else b.push_back(-tmp);
}
sort(a.begin(),a.end());
sort(b.begin(),b.end());
for (int i=a.size()-1;i>=0;i-=k){
ans+=1ll*a[i];
}
for (int i=b.size()-1;i>=0;i-=k){
ans+=1ll*b[i];
}
ans*=2;
ans-=max(a[a.size()-1],b[b.size()-1]);
printf("%lld\n",ans);
}
return 0;
}
A题,这题面也忒长了吧!!
真正有用的好像只有后面一段:
现在要跳舞,给出男生身高,女生身高,有些男女搭配跳舞,有的人只想和比自己高的人跳,有的人只想和比自己矮的人跳,问:最多可以匹配出多少对?
哦?怕不是一道二分图匹配?
显然不是,这道题中有4种人:
显然只能1 4搭配,2 3搭配,怎样搭配捏?排序后两个指针扫一下不久行了吗?
AC
#include
using namespace std;
const int maxn=100005;
int n,m;
vector<int> mt,ms,wt,ls;
int a[maxn],b[maxn];
int main(){
int cas;
scanf("%d",&cas);
while(cas--){
int ans=0;
mt.clear();
ms.clear();
wt.clear();
ls.clear();
scanf("%d%d",&n,&m);
for (int i=1;i<=n;i++) scanf("%d",&a[i]);
for (int i=1;i<=m;i++) scanf("%d",&b[i]);
for (int i=1;i<=n;i++){
int k;
scanf("%d",&k);
if (k==1) mt.push_back(a[i]);
else ms.push_back(a[i]);
}
for (int i=1;i<=m;i++){
int k;
scanf("%d",&k);
if (k==1) wt.push_back(b[i]);
else ls.push_back(b[i]);
}
sort(mt.begin(),mt.end());
sort(ms.begin(),ms.end());
sort(wt.begin(),wt.end());
sort(ls.begin(),ls.end());
int i=0,j=0;
while(i<ls.size() && j<mt.size()){
if (ls[i]>mt[j]) ans++,i++,j++;
else i++;
}
i=0,j=0;
while(i<ms.size() && j<wt.size()){
if (ms[i]>wt[j]) ans++,i++,j++;
else i++;
}
printf("%d\n",ans);
}
return 0;
}
然后我们就入坑了B题:
好复杂的题面:
它定义了一坨名词:
e-prime:不能拆成两个偶数的数
e-prime分解:把一个数拆分成一堆e-prime乘积的形式
e-阶乘:e!!:就是用偶数做阶乘
给你一个n,问你n!!最多可以被分解成多少个e-prime
好难啊!左想想,右想想,A出这道题的人越来越多了!!!
忒难了吧!
哦,等等等,这个even是啥意思,偶数!!!!!!!!!!!!!!!
e-prime只能是偶数,呃……
那么只要有一个2我们就可以分解出一个e-prime,那就要看由于n!!的每一项都有一个2,那我们就是要看(n/2)!里有多少个2就行了,简单,还要高精度!!!
(不知道比赛结束后,我打了一遍就tle了,大佬发现错误可以在评论中回复,谢谢)
2019.5.3upd:我居然过了,结构体里面的数组开大了!
tle代码:
#include
using namespace std;
char ch[2005];
struct BIG_NUM{
int a[2005],len;
void insert(char *s){
len=strlen(s);
for (int i=0; i<len; i++)
a[len-i]=s[i]-'0';
}
void clear(){
len=0;
memset(a,0,sizeof(a));
}
}n;
BIG_NUM operator + (BIG_NUM a, BIG_NUM b) {
BIG_NUM c;
c.clear();
c.len=max(a.len,b.len)+1;
for (int i=1;i<=c.len;i++){
c.a[i]=a.a[i]+b.a[i]+c.a[i];
c.a[i+1]=c.a[i]/10;
c.a[i]=c.a[i]%10;
}
while(c.a[c.len]==0) c.len--;
return c;
}
BIG_NUM operator / (BIG_NUM a, int b) {
BIG_NUM c;
c.clear();
c.len=a.len;
int x=0;
for (int i=a.len;i>=1;i--){
int tmp=(a.a[i]+x)/b;
x=(a.a[i]+x)%b*10;
c.a[i]=tmp;
}
while(c.a[c.len]==0) c.len--;
return c;
}
int main(){
int cas;
scanf("%d",&cas);
while(cas--){
BIG_NUM ans;
ans.clear();
scanf("%s",ch);
n.insert(ch);
if (n.len==1 && n.a[1]==1) {
printf("1\n");
continue;
}
n=n/2;
ans=n;
while(n.len>0){
n=n/2;
ans=ans+n;
}
for (int i=ans.len;i>=1;i--){
printf("%d",ans.a[i]);
}
puts("");
}
return 0;
}
啊,封榜了
C题走起
题面太麻烦了,自行体会:C题
“呃,这一定会出循环呀!”
“那怎么样会出循环捏?”
“……”
“管他呢,直接循环5000000次好了”
T了
“那试试2000000次”
A了
A得好突然!
#include
using namespace std;
char ch[250];
int n,m,aa,bb,a[2005][2005];
long long k;
int calc(int i,int j){
return 81*a[i][j]+27*a[i-1][j]+9*a[i+1][j]+3*a[i][j-1]+a[i][j+1];
}
int main(){
int cas;
scanf("%d",&cas);
while(cas--){
int ans=0;
scanf("%d%d%d%d%lld",&n,&m,&aa,&bb,&k);
scanf("%s",ch);
for (int i=1;i<=n;i++){
for (int j=1;j<=m;j++){
scanf("%1d",&a[i][j]);
}
}
k=min(k,1ll*2000000);
int x=aa,y=bb;
char tmp;
for (int i=1;i<=k;i++){
tmp=ch[calc(x,y)];
if (tmp=='U'){if (a[x-1][y]!=1) x--;}
else if (tmp=='D'){if (a[x+1][y]!=1) x++;}
else if (tmp=='L'){if (a[x][y-1]!=1) y--;}
else if (tmp=='R'){if (a[x][y+1]!=1) y++;}
else if (tmp=='P'){if (a[x][y]==2) a[x][y]=0,ans++;};
}
printf("%d\n",ans);
}
return 0;
}
嗯,这题还有续集!
顺理成章地来到了D题,What,让你写个命令然后special judge!intereseting
推了半天,WA了29发,然后Game over!
A了6道题,我们还是尽力了,今年应该没有ACM了,下次加油!
与HG机房