A: 贪吃的zhazhahe
最开始的思路是假如5张饼4个空,就先2次搞好4个饼,再2次一个饼共4次,但显然错了,其实3次就可以,分别为1+,2+,3+,4+;5+,1-,2-,3-;4-,5-。问题出在最后有空但由于不能同时搞一张饼的两面而产生浪费,因此策略就是先尽量把所有饼的正面都搞好,再考虑反面。于是就产生了我下面的鬼畜代码,真的不堪入目。考虑了具体分配方法了,而题目只需要次数。。。
#include<iostream>
using namespace std;
int main()
{
int t,n,k;
cin>>t;
while(t--)
{
cin>>n>>k;
cout<<n/k+(bool)(n%k)+(n-(k-n%k)%k)/k+(bool)((n-(k-n%k)%k)%k)<<endl;
}
return 0;
}
后来看大佬的blog,发现直接把n个饼的2n个面连排,看成2n个面,比如5个饼:1+,2+,3+,4+,5+,1-,2-,3-,4-,5-。然后依次放就好了。结果就是2*n/k(整除时),或者2*n/k+1(不整除时)
自己又想了想,这两种都有漏洞,那就是若2*n<=k时,这时直接答案一定是2,事实上,n<=k时答案就是2.
B: 签到题
不知道为什么char数组就过了,而单字符和c++string都始终wa,太玄学了。
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int main()
{
int t;
char n[505];
cin>>t;
while(t--)
{
scanf("%s",n);int len=strlen(n);
int sum=0;
for(int i=0;i<len;i++)sum+=n[i]-'0';
cout<< (sum%3==0 ? "Three people are the most stable" : "Why would it be like this");
cout<<endl;
}
return 0;
}
C: 算罚时
#include<iostream>
using namespace std;
int main()
{
int t,a,b;
cin>>t;
while(t--)
{
int suma=0,sumb=0;
for(int i=0;i<8;i++)scanf("%d:%d",&a,&b),suma+=a,sumb+=b;
cout<<suma*60+sumb<<endl;
}
return 0;
}
D: 有趣的游戏
第一次做这种题,博弈论,其实题目初始给定的状态就决定了两人谁必胜谁必败,会有一个人无论多聪明也无法摆脱必败的定局。思想来自大佬的bloghttps://blog.csdn.net/bcwan_/article/details/53377375
类型:博弈
分析:这种类型题的基本思路是找到一种恒定不变的方式,使得对方无论怎么拿,你都能找到对应要拿的数量
举个例子,假如n=22,取的区间为[1,2],那么小师妹第一次拿走1个,
使得剩下的数量21,是区间左右端点之和的倍数,即3的倍数.
那么无论对方怎么拿,我们都能维持剩下来的数量是3的倍数的状态不变,比如他拿1个,你就拿2个,或者他拿2个,你就拿1个
始终保持他能拿,我必能拿的状态,那么只要判断初始情况,我就知道我能不能稳赢
回顾刚刚的拿法,我们很容易推出一个方式判断第一个人应该如何拿,即余数=n%(L+R)
1.假设这个余数落在[L,R]里面,那么小师妹第一次把余数全抓走,剩下的是(L+R)的倍数,我们知道,小师妹稳赢
2.假设这个余数为L-k (0<k<=L)里面,那么因为只能抓[L,R]个珠子,小师妹动不了余数这个数目,她只能先动(L+R)里面合法的某些数目,那么第二个人能对应着拿掉小师妹在(L+R)里面剩下的数目,情况变成小师妹稳输
3.假设这个余数落在R+L-k (0<k<L)里面,那么小师妹第一次拿走R个,剩下的数目为L-k即把第二种状态丢给对方,小师妹稳赢
所以题目可以解决.
-----------------------------------------------------来自https://blog.csdn.net/bcwan_/article/details/53377375
#include<cstdio>
#include<iostream>
using namespace std;
int t,n,l,r;
int main()
{
cin>>t;
while(t--)
{
cin>>n>>l>>r;
int ans=n%(l+r);
if(ans>=l&&ans<=r)cout<<"Win\n";
else if(ans<l)cout<<"Lose\n";
else if(ans>r)cout<<"Win\n";
}
return 0;
}
E:套套套
嵌套矩形,先将所有矩形化为标准形式(a,b)其中a<=b,然后按a排序,若满足题意,则不存在两个矩形a相等,或a1<a2且b1>=b2。后来看大佬的blog,发现直接按面积排序也可以,如果满足题意,一定按面积从小到大满足前面的长宽分别小于后面的。
#include<iostream>
#include<algorithm>
using namespace std;
int t,n,x[10005],y[10005],d[10005];
bool cmp(int a,int b)
{
return x[a]<x[b] ;
}
int main()
{
cin>>t;
while(t--)
{
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>x[i]>>y[i];
if(x[i]>y[i])swap(x[i],y[i]);
}
bool ok=1;
for(int i=1;i<=n;i++)d[i]=i;
sort(d+1,d+1+n,cmp);
for(int i=1;i<=n-1;i++)if(x[d[i]]==x[d[i+1]]||y[d[i]]>=y[d[i+1]]){ok=0;break;}
printf(ok?"Yes\n":"No\n");
}
return 0;
}
F: 吃豆豆
算一个数的二进制表示有几个1。自己想的通过&1得到每一位的值,后来看dl的blog通过不断/2%2也可以实现。
#include<iostream>
using namespace std;
int main()
{
long long a;
while(scanf("%lld",&a)&&a!=-1)
{
int sum=0;
for(int i=0;i<63;i++)if(((long long)1<<i)&a)sum++;
cout<<sum<<endl;
}
return 0;
}
G: Pigofzhou和他的那么多个学妹
记录x页作为分界点的边界敲击次数,然后判断输入在哪个分界点的右边,然后就可以根据输入与边界的差轻松地算出具体是多少页。
#include<cstdio>
using namespace std;
int t;
long long a;
long long tot[15];
int main()
{
tot[1]=9;
for(int i=2;i<=13;i++)tot[i]=tot[i-1]*10;
for(int i=1;i<=13;i++)tot[i]*=i;
for(int i=2;i<=13;i++)tot[i]+=tot[i-1];
scanf("%d",&t);
while(t--)
{
scanf("%lld",&a);
int pos=13;
while(a<=tot[pos])pos--;
long long last=(a-tot[pos])/(pos+1);
long long num=1;
for(int i=0;i<pos;i++)num*=10;
num+=last-1;
printf("%lld\n",num);
}
return 0;
}
H: 神奇的清华大大的神奇魔法
首先第一优先考虑不消耗魔法值,即尽量不改变字母,但注意改变字母顺序不消耗魔法值,因此字符串的先后序列不重要,只需要知道每个字符有多少个,在消耗魔法值尽可能少的前提下,按字典序依次输出各个字符数目的一半(因为是回文串,所以串的字典序完全取决于前一半)。对于长度为偶数,必须每个字符都有偶数个,奇数则只有一个字符奇数个,其余偶数个。具体思路实在懒得写了,见代码。
#include<cstdio>
using namespace std;
int t;
char s[200005];
int tot[26];
int main()
{
scanf("%d",&t);
while(t--)
{
for(int i=0;i<26;i++)tot[i]=0;
scanf("%s",s);
for(int i=0;s[i];i++)tot[s[i]-'a']++;
for(int pos=0;pos<26;pos++)
{
if(tot[pos]%2)
{
for(int i=25;i>=pos;i--)if(tot[i]%2){tot[i]--;break;}
tot[pos]++;
}
}
for(int i=0;i<26;i++)if(tot[i])
{
for(int j=0;j<tot[i]/2;j++)printf("%c",'a'+i);
}
for(int i=0;i<26;i++)if(tot[i]%2)printf("%c",'a'+i);
for(int i=25;i>=0;i--)if(tot[i])
{
for(int j=0;j<tot[i]/2;j++)printf("%c",'a'+i);
}
putchar('\n');
}
return 0;
}
I:神枪手TMK
不说了
J: 神龙的烦恼
按价格从小到大买就行了。
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
int n,m;
int num[100005],cost[100005],d[100005];
bool cmp(int a,int b)
{
return cost[a]<cost[b];
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)scanf("%d%d",&num[i],&cost[i]);
for(int i=1;i<=n;i++)d[i]=i;
sort(d+1,d+1+n,cmp);
long long ans=0;
for(int i=1;i<=n;i++)
{
if(m==0)break;
ans+=min(m,num[d[i]])*cost[d[i]];
m-=min(m,num[d[i]]);
}
cout<<ans<<"\n";
return 0;
}