先扔一波题目
A | 托米的赌球 |
这一题的大意就是托米有一些面值不同的硬币,想用尽量少的硬币凑出给出的值。
这题刚看到的时候还以为是DP,或者是数论(前几天做这类题做疯了),但一看数据范围……果断排除。
重新看了一下托米有的硬币的面值,这不就是贪心吗,每次能用面值大的就用面值大的,然后就很开心地去写代码了。
#include
#define mem(x) memset(x,0,sizeof(x));
using namespace std;
int p[15]={10000,5000,2000,1000,500,200,100,50,20,10,5,2,1};//直接用分
long long ans[15],t,n,m;//注意范围 10^9 * 100 > 2^31-1
int main(){
cin>>t;
while(t--){
mem(ans);
cin>>n>>m;
n=n*100+m; //把它转成分的形式
for(int i=0;i<13;i++){
ans[i]=n/p[i];
n%=p[i];
}
for(int i=0;i<13;i++) printf("%lld ",ans[i]); if(t)printf("\n");//注意格式(罚时20m)
}
return 0;
}
B | 托米的划分 |
这题刚看到的时候是有些懵逼的,于是打表找规律 于是我就想,对于每个数肯定有一种固定的分法,于是凭借我强大的猜测力(乱搞能力)推测(乱捅)出了分法。
就是比如说当前的数字是n,就把它分成 (1,n-1)然后n-1再继续分下去,我们可以发现就是求1~n-1的和,就是n*(n-1)/2。
代码嘛,100b了:
#include
using namespace std;
long long t,n;//注意变量类型
int main(){
cin>>t;
while(t--){
cin>>n;
cout<<(n)*(n-1)/2<
C | 托米的位运算 |
第三题嘛……
其实一开始是没看懂题目,原来是很简单的,就是给出一些数,要从中取出一些数,使他们所有数按位与的结果的lowbit值最大的情况下还要然选出来的数尽量多。
这题一开始想了两个贪心,结果一个28.几%,令一个71.几%,加起来刚好100%……
后面有换了种思想,就是我没可以枚举这个lowbit值,然后把这一位是一的全部选出来,看最后按位与的结果是否lowbit值刚好为我枚举的,看了我的代码就懂了(还是挺短的)
#include
#define lowbit(x) x & -x //lowbit在这!!
using namespace std;
const int N = 100005;
int sz,n,a[N],ans[N];
int main(){
int p=0;
scanf("%d", &n);
for(int i=1;i<=n;i++) scanf("%d",&a[i]);//日常输入
for(int i=30;i>=0;i--){ //枚举看是哪一位为一(lowbit值)
int s=2147483647; // 2^31 -1 ->(1111……1)2
sz=0;
p=(1<
D | 托米的咒语 |
这题的题意也比较好理解吧,就是看a……i的排列有几个出现在了字符串s里面。
这题正常人的思路就是枚举全排列,然后带进去试,我一开始也是这么想的,但算了一下最坏时间复杂度9!*3000≈10^9
会超时(但赛后听说它们就是这样卡过了!!),我的方法也十分简单明了,就是在枚举全排列的基础上,在匹配的
的时候做了一些优化,首先,对于我们当前要匹配的一个字母,如有多个满足条件的我们是不是会贪心地取最前面一个满足要求的,这里我们可以用二分查找来优化,所以总的时间复杂度就是O(log2(|s|))的,只不过常数是9!*9,有点大,不过比起前面那个还是好了很多。
看了代码就懂了:
#include
using namespace std;
const int N = 3005;
int zm[11][N],sz[11],d[11],p[11],ans;
string st;
bool check(){
int pos=0;//pos 为当前匹配到 s 的第几位
for(int i=1;i<=9;i++){//把排列带进去check一下
int pj=pos;//临时变量
pos=lower_bound(zm[p[i]]+1,zm[p[i]]+1+sz[p[i]],pj) - zm[p[i]];
if(zm[p[i]][pos]<=pj) pos++; //判断是否在上一个位置之后
pos=zm[p[i]][pos];
if((st[pos]-'a')!=p[i]) return 0; //是否有这个字母可以满足要求
}
return 1;
}
void dfs(int x){//枚举全排列
if(x>=9){
ans+=check();
return;
}
for(int i=0;i<9;i++){
if(!d[i]){
d[i]=1;
p[x+1]=i;
dfs(x+1);
d[i]=0;
}
}
}
int main(){
cin>>st;
int n=st.length();
st=" "+st; //方便处理……
for(int i=1;i<=n;i++){
if(st[i]<='i') zm[st[i]-'a'][++sz[st[i]-'a']]=i;//把每个位置按字母分类
}
dfs(0);
printf("%d",ans);//开心地输出答案
return 0;
}
待填坑……(其实是题解还没出)
题解链接->官方的:https://uploadfiles.nowcoder.com/files/20180728/8030387_1532751445741_%E7%89%9B%E5%AE%A2%E7%BB%83%E4%B9%A0%E8%B5%9B23%E9%A2%98%E8%A7%A3.pdf