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