来自FallDream的博客,未经允许,请勿转载,谢谢。
------------------------------------------------------
A.Anastasia and pebbles
你有两个口袋,每种口袋最多只能装k个物品,有n种物品,每种物品有ai个,两种不同的物品不能混在一起,问最少要装多少次.
题解:.............
#include<iostream>
#include<cstdio>
#include<cmath>
#include<queue>
#include<cstring>
#include<queue>
#include<algorithm>
#include<map>
#define ll long long
using namespace std;
inline int read()
{
int x=,f=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-') f=-;ch=getchar();}
while(ch>=''&&ch<=''){x=x*+ch-''; ch=getchar();}
return x*f;
} ll n,k;
ll ans=; int main()
{
n=read();k=read();
for(int i=;i<=n;i++)
{
ll x=read();
ans+=(x+k-)/k;
}
cout<<(ans+)/;
return ;
}
B.Masha and geometric depression
给定一个等比数列,第一项是b1,之后每一项是前一项乘以q,但是b1和q都可以是负数或0。你还有m个不吉利的数字。每当满足abs(b)<=l的时候,你会把b写出来,除非它是一个不吉利的数字。
问你会写出多少个数字,当然你可能写出无限多的数字。
题解:大判断。 一开始我以为不满足还能继续写....结果pretest WA了一排...
#include<iostream>
#include<cstdio>
#include<cmath>
#include<queue>
#include<cstring>
#include<queue>
#include<algorithm>
#include<map>
#define ll long long
using namespace std;
inline int read()
{
int x=,f=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-') f=-;ch=getchar();}
while(ch>=''&&ch<=''){x=x*+ch-''; ch=getchar();}
return x*f;
} int b1,q,l,m;
map<int,bool> mp; inline int abs(int x){return x<?-x:x;} int main()
{
b1=read();q=read();l=read();m=read();
if(abs(b1)>l) return *puts("");
for(int i=;i<=m;i++)mp[read()]=;
if(b1==)
{
if(mp[])return *puts("");
else return *puts("inf");
}
if(q==)
{
if(!mp[])return *puts("inf");
if(abs(b1)<=l&&!mp[b1]) return *puts("");
puts("");
return ;
}
if(q==)
{
if(abs(b1)<=l&&!mp[b1])return *puts("inf");
else return *puts("");
}
if(q==-)
{
int ans=;
if(abs(b1)<=l&&!mp[b1])ans++;
if(abs(b1)<=l&&!mp[-b1]) ans++;
if(ans) return *puts("inf");
else return *puts("");
}
else
{
int ans=(abs(b1)>l||mp[b1])?:;
while(1LL*abs(q)*abs(b1)<=(ll)l)
{
b1*=q;
if(abs(b1)<=l&&!mp[b1])ans++;
}
cout<<ans<<endl;
}
return ;
}
C.Functions again
给定一个数字序列ai和函数f,求f的最大值。 $n\leqslant 100000$
题解:发现每一种$|a[i]-a[i+1]|$只有两种不同的贡献,分开计算即可。
#include<iostream>
#include<cstdio>
#include<cmath>
#include<queue>
#include<cstring>
#include<queue>
#include<algorithm>
#define ll long long
#define INF 1000000000
#define MN 100000000
using namespace std;
inline ll read()
{
ll x=,f=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-') f=-;ch=getchar();}
while(ch>=''&&ch<=''){x=x*+ch-''; ch=getchar();}
return x*f;
} int n;
int a[];
ll f[],f2[];
ll ans=;
int abs(int x){return x<?-x:x;} int main()
{
n=read();
for(int i=;i<=n;i++)a[i]=read();
for(int i=;i<=n;i++) f[i]=f[i-]+1LL*(i&?:-)*abs(a[i]-a[i+]);
for(int i=;i<=n;i++) f2[i]=f2[i-]+1LL*(i&?-:)*abs(a[i]-a[i+]);
ll minn=;
for(int i=;i<n;i++)
{
ans=max(ans,f[i]-minn);
if(i%==)minn=min(minn,f[i]);
}
minn=f2[];
for(int i=;i<n;i++)
{
// cout<<i<<" "<<f2[i]<<" "<<ans<<" "<<minn<<endl;
ans=max(ans,f2[i]-minn);
if(i&)minn=min(minn,f2[i]);
}
cout<<ans<<endl;
return ;
}
D. Weird journey
给定一个无向图,可能有自环,无重边,你要求出满足恰好有两条边只走了一次,其它都走了两次的路径数量。两种方案不同当且仅当边不同。 $n,m\leqslant 10^{6}$
题解:先判联通。然后我们把自环和普通边分开考虑。
如果都选普通边,那么这两条边一定要有公共点,用度数计算一下即可。
如果一个选自环,那么显然任意普通边都能成为另一条边。
如果两个都选自环,那么显然没问题。
#include<iostream>
#include<cstdio>
#define ll long long
#define MN 1000000
using namespace std;
inline int read()
{
int x = , f = ; char ch = getchar();
while(ch < '' || ch > ''){ if(ch == '-') f = -; ch = getchar();}
while(ch >= '' && ch <= ''){x = x * + ch - '';ch = getchar();}
return x * f;
} int n,m,cnt=,head[MN+],num=,num2=,s[MN+];
struct edge{int to,next;}e[MN*+];
ll ans=;
bool mark[MN+],b[MN+];
void ins (int f,int t){e[++cnt]=(edge){t,head[f]};head[f]=cnt;} void dfs(int x)
{
mark[x]=;
for(int i=head[x];i;i=e[i].next)
if(!mark[e[i].to])
dfs(e[i].to);
} int main()
{
n=read();m=read();
for(int i=;i<=m;i++)
{
int u=read(),v=read();
if(u==v) num2++,b[u]=;
else ins(u,v),ins(v,u),num++,s[u]++,s[v]++;
}
for(int i=;i<=n;i++)
if(b[i]||head[i])
{
dfs(i);break;
}
for(int i=;i<=n;i++) if(!mark[i]&&(head[i]||b[i])) return *puts("");
for(int i=;i<=n;i++) ans+=1LL*s[i]*(s[i]-)/;
ans+=1LL*num2*(m-num2)+1LL*num2*(num2-)/;
printf("%lld",ans);
return ;
}
E. The Great Mixing
给定n个数ai,你要从中选出最少的数,每个数可以选任意次,使得平均值等于k $n\leqslant 10^{6} , ai,k\leqslant 1000$
题解:显然n最多只有1000种,然后我们分成正的和负的考虑。我们发现我们选的数的总和不会超过$10^{6}$,所以直接bfs就可以了,复杂度不是满的,应该能比较快找出答案。
数据挺水的,直接dp好像也能过。
#include<iostream>
#include<cstdio>
#define MAXN 1000000
using namespace std;
inline int read()
{
int x = , f = ; char ch = getchar();
while(ch < '' || ch > ''){ if(ch == '-') f = -; ch = getchar();}
while(ch >= '' && ch <= ''){x = x * + ch - '';ch = getchar();}
return x * f;
} int n,k;
bool mark[];
int s[],q[MAXN+],top=,cnt=,d[MAXN+]; int main()
{
k=read();n=read();
for(int i=;i<=n;i++)
{
int x=read()-k+;
if(!mark[x]) mark[x]=,s[++cnt]=x-;
}
d[]=;
for(int i=;i<=top;i++)
for(int j=;j<=cnt;j++)
{
if(s[j]+q[i]==) return *printf("%d",d[q[i]]);
if(s[j]+q[i]<=MAXN&&s[j]+q[i]>=&&!d[s[j]+q[i]]) d[s[j]+q[i]]=d[q[i]]+,q[++top]=s[j]+q[i];
}
puts("-1");
return ;
}