给出n个字母,从中挑选k个排成一列使得后一个在字母表中至少是前一个的后两位.求这个序列最小的字母值的和,无解输出-1.
简单贪心,注意a的值是1而不是0.
char save[M];
int main(void)
{
int n=read(),k=read();
scanf("%s",save);
sort(save,save+n);
int ans = 0, now = -2,len = 0;
for(int i=0;iif(save[i]>now+1)
{
now = save[i];
ans += save[i]-'a'+1;
len++;
}
}
printf("%d\n",len1:ans );
return 0;
}
有n(100)个人和m(100)单位食品,每单位食品都有一个种类(有的相同),一个人如果吃了一种食品就再也不能吃其他种类的食品,每人每天需要消耗一单位食品,问这些人最多能坚持几天?
小数据,暴力.
int save[M];
int main(void)
{
int n=read(),m=read();
map<int,int> mp;
for(int i=0;iint ans = 0;
for(;;ans++)
{
int tmp = 0;
for(auto x:mp)
tmp+=x.second/(ans+1);
if(tmpbreak;
}
printf("%d\n",ans );
return 0;
}
这个题满足二分性质.
比赛时WA一次,循环上限写错了.
飞船要按顺序飞n(1000)个星球,只有起飞和降落会消耗燃料,每个星球的每个过程都有一个独立的比值k(1<=k<=1000),设当前飞船总重(包括燃料)为M,则这个过程会消耗M/k的燃料.给定所有的k与飞船自重,问在起点最少装多少燃料可以飞完全程.
飞行的顺序是没有影响的,每次相当于总重乘上(k-1)/k,所以只要有一个k为1就无解.
可以证明,飞完全程所需要的燃料是满足二分性质的,但本题可以不用二分来做.
设自重为M,最少需要燃料X,则有
int save[M];
int main(void)
{
int n = 2 * read(), m = read();
double A = 1.0;
while(n--)
{
int k = read();
if(k==1)
{
printf("-1\n");
return 0;
}
A *= k;
A /= k-1;
}
printf("%.7f\n",m*A-m );
return 0;
}
猜数字游戏,数字范围1e9,最多猜60次,每次给出提示(大/小/正确),但是提示是会出错的,有一个长n(30)位的内置序列,序列为1时出错,为0时正确.
先猜n次1把序列试出来,然后二分解决.
int save[M];
int main(void)
{
int m=read(),n=read();
for(int i=0;iprintf("%d\n",1 );
fflush(stdout);
save[i] = read();
if(save[i]==0)
return 0;
}
int l = 2, r = m, cnt = 0;
while(1)
{
int mid = (l+r)>>1;
printf("%d\n",mid );fflush(stdout);
int p = read() * save[cnt++ % n];
if(p==0) return 0;
else if(p==1) l=mid+1;
else r = mid-1;
}
return 0;
}
得到的一个结论是交互题的读入输出不会与快读冲突,测试时最好手动输入数据.
比赛时因为二分多了两个罚时,复习一下:
int l=1,r=len,ans=-1;
while(l<=r)
{
int mid = (l+r)>>1;
if(check(mid,n,m)) ans = mid, l = mid + 1;
else r = mid - 1;
}
带一个ans之后可以说是非常好写了,注意右移位不要写反!
给定n(1e5)个数字(1e9)和一个进制k(1e5),考虑任意多个这些数字的组合,问从0到k-1中哪些数可以成为k进制下这些数字组合的个位数?所有输入输出均使用十进制.
所有的数字模k后与k取gcd,就是最小可以表示的数字间隔.
证明参见
裴蜀定理
若a,b是整数,且(a,b)=d,那么对于任意的整数x,y,ax+by都一定是d的倍数.
特别地,一定存在整数x,y,使ax+by=d成立。
推论:a,b互质的充要条件是存在整数x,y使ax+by=1.
int main(void)
{
int n=read(),k=read(),ans=k;
while(n--)
ans = __gcd(ans,read()%k);
printf("%d\n",k/ans );
for(int i=0;iprintf("%d ",i );
return 0;
}
给定一个逻辑表达式,包括若干个值确定的01变量,以及NOT,OR,AND,XOR运算符.问对每一个变量取非时逻辑表达式的值,式子以树形给出.
首先计算出表达式的原始值,然后对于这棵树的每个节点,从上到下记录每个节点的值改变时根节点的值是否会改变.注意如果一个节点值改变不影响根节点值,那么它的子节点也不会影响根节点的值,可以省下很多时间.
最后将所有叶子节点的结果输出即可,总复杂度O(n).
/* LittleFall : Hello! */
#include
using namespace std; typedef long long ll;
inline int read(); inline void write(int x);
const int M = 1000016, MOD = 1000000007;
const char ops[5][5]={"IN","NOT","AND","OR","XOR"};
struct Node
{
int val;
int op; //0-in,1-not,2-and,3-or,4-xor
int son[2];
int ans;
}save[M];
int getval(int id)
{
switch(save[id].op)
{
case 0: return save[id].val;
case 1: return save[id].val = !getval(save[id].son[0]);
case 2: return save[id].val = getval(save[id].son[0]) & getval(save[id].son[1]);
case 3: return save[id].val = getval(save[id].son[0]) | getval(save[id].son[1]);
case 4: return save[id].val = getval(save[id].son[0]) ^ getval(save[id].son[1]);
}
return 0;
}
void getans(int id)
{
save[id].ans = 1;
if(save[id].op==1)
getans(save[id].son[0]);
if(save[id].op<2)
return;
int son1 = save[id].son[0], son2 = save[id].son[1];
if(save[id].op==2)
{
if(((!save[son1].val) & save[son2].val) != save[id].val)
getans(son1);
if(((!save[son2].val) & save[son1].val) != save[id].val)
getans(son2);
}
if(save[id].op==3)
{
if(((!save[son1].val) | save[son2].val) != save[id].val)
getans(son1);
if(((!save[son2].val) | save[son1].val) != save[id].val)
getans(son2);
}
if(save[id].op==4)
{
if(((!save[son1].val) ^ save[son2].val) != save[id].val)
getans(son1);
if(((!save[son2].val) ^ save[son1].val) != save[id].val)
getans(son2);
}
}
int main(void)
{
#ifdef _LITTLEFALL_
freopen("in.txt","r",stdin);
#endif
int n=read();
char tmp[5];
for(int i=1;i<=n;i++)
{
scanf("%s %d",tmp,&save[i].son[0]);
for(int j=0;j<5;j++)
if(strcmp(tmp,ops[j])==0)
save[i].op = j;
if(save[i].op==0)
save[i].val = save[i].son[0];
if(save[i].op>1)
save[i].son[1] = read();
}
int base = getval(1);
getans(1);
for(int i=1;i<=n;i++)
if(save[i].op==0)
printf("%d",save[i].ans^base );
return 0;
}
inline int read()
{
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9') {if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
inline void write(int x)
{
if(x<0) putchar('-'),x=-x;
if(x>9) write(x/10);
putchar(x%10+'0');
}