您的位置:首页 > 其它

CodeCraft-18 and Codeforces Round #458(Div. 1+Div. 2,combined)

2018-01-22 17:04 525 查看
A. Perfect Squares

题意:给定一个序列,求序列中最大的完全平方数

这个题,就是送分的嘛,直接检测(int)n√*(int)n√是否等于n就好了

B.Conan and Agasa play a Card Game

题意:给定n个整数,两个玩家轮流取数,取走这个数的同时,所有比这个数小的数也会被取走,取到最后一个数的人赢

这道题也比较水,考虑a序列中最大值的个数

若最大值为奇数个,玩家直接取最大值,必胜

若最大值为偶数个,玩家取最大值必败

所以玩家必然不能取最大值,只能取次大值

对次大值个数也照此分析,先手玩家想要赢,只能取序列从大到小排序第一个数量为奇数的数。如果存在,先手必胜;若不存在,后手必胜。

C.Travelling Salesman and Special Numbers

题意:定义一种数的操作,可将一个正整数变为它转成二进制后二进制位上1的个数。例如:1310=11012,进行如上所述的操作后13会变为3

现在要求小于等于n(1≤n<21000)的最少能通过k次操作变成1的数的个数(其实就是1不能再进行操作)

看上去数据范围非常的反人类,实际上,只需要一次操作,所有的数就会变成1000以内的数,所以我们可以用模拟求出所有可以通过k-1次操作变成1的数,时间复杂度O(k2)

然后这个问题就转换成求n以内有x个1的数的个数,这个用组合数dp,统计一下答案就好了,贴上我弱弱的代码

#include<cstdio>
#include<cstring>
#include<algorithm>
const int mod=1e9+7;
int n,m,p,z,tot,len,a[1005][1005],cnt[1005],X,Y,b[1005],c[1005],f[1005][1005],ans;char s[1005];
inline int calc(int x)
{
z=tot;int t=0;
for(int i=len-1;i>=0;--i)
if(s[i]=='1')
{
--z;if(z>x)continue;
(t+=f[len-i-1][x-z])%=mod;
}
return t;
}
int main()
{
scanf("%s%d",s,&n);
len=strlen(s);
if(n==0){printf("%d",1);return 0;}
for(int i=0;i<len;++i)
if(s[i]=='1')++tot;
for(int i=2;i<=1000;++i)
{
X=0;Y=i;
for(;Y;Y-=(Y&-Y),++X);
a[X][++cnt[X]]=i;
}
int *x=b,*y=c,*t;
x[m=1]=1;
for(int l=1;l<n;++l)
{
p=0;
for(int i=1;i<=m;++i)
{
X=x[i];
for(int j=cnt[X];j;--j)
y[++p]=a[X][j];
}
t=x;x=y;y=t;m=p;
}
for(int i=1;i<=m;++i)b[i]=x[i];
std::sort(b+1,b+m+1);
for(int i=0;i<=1000;++i)f[i][0]=f[i][i]=1;
for(int i=1;i<=1000;++i)
for(int j=1;j<i;++j)
f[i][j]=(f[i-1][j]+f[i-1][j-1])%mod;
for(int i=1;i<=m;++i)
{
if(tot==b[i])++ans,ans%=mod;
(ans+=calc(b[i]))%=mod;
}
if(n==1)--ans;
printf("%d",ans);
}


D. Bash and a Tough Math Puzzle

题意:给定一个序列,需要支持两种操作

1:单点修改 2:求是否能在最多只改变一个数的情况下使得[l,r]区间的gcd变为x

很容易想到线段树维护gcd,问题在于如何维护,显然区间中如果存在两个以上的数不是x的倍数,则输NO,否则输YES

询问时如果有一个区间的gcd不是x的倍数,二分检测是否有某两个子区间的gcd都不为x的倍数,累加各个区间询问的答案判断即可

讲得可能不那么清楚,贴上代码以助理解

#include<cstdio>
#define lc x<<1
#define rc x<<1|1
const int N=2000005;
int n,m,t
,y,z,L,R;
inline int gcd(int a,int b){return !b?a:gcd(b,a%b);}
inline int read()
{
int t=0,c=getchar();
for(;c<48||c>57;c=getchar());
do
{
t=(t<<1)+(t<<3)+c-48;
c=getchar();
}
while(47<c&&c<58);
return t;
}
inline void build(int x,int l,int r)
{
if(l==r)
{
t[x]=read();
return;
}
int mid=l+r>>1;
build(lc,l,mid);
build(rc,mid+1,r);
t[x]=gcd(t[lc],t[rc]);
}
inline void modify(int x,int l,int r)
{
if(l==r)
{
t[x]=z;
return;
}
int mid=l+r>>1;
if(y<=mid)modify(lc,l,mid);
else modify(rc,mid+1,r);
t[x]=gcd(t[lc],t[rc]);
}
inline bool divide(int x,int l,int r)
{
if(l==r)return false;
int mid=l+r>>1;
if(t[lc]%y!=0&&t[rc]%y!=0)return true;
else if(t[lc]%y!=0)return divide(lc,l,mid);
else return divide(rc,mid+1,r);
}
inline int query(int x,int l,int r)
{
if(L<=l&&r<=R)
{
if(t[x]%y!=0)return 1+divide(x,l,r);
else return 0;
}
int mid=l+r>>1;
if(L>mid)return query(rc,mid+1,r);
else if(R<=mid)return query(lc,l,mid);
else return query(lc,l,mid)+query(rc,mid+1,r);
}
int main()
{
scanf("%d",&n);
build(1,1,n);
m=read();
while(m--)
{
if(read()==1)
{
L=read();R=read();
y=read();
if(query(1,1,n)<2)printf("YES\n");
else printf("NO\n");
}
else
{
y=read();z=read();
modify(1,1,n);
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐