比赛链接:北方大学ACM多校训练第十四周
题解
A:卡尔的连招
B:
#include<bits/stdc++.h>
using namespace std;
const int N=1e4+7;
int a[N],pre[N];
int main()
{
//freopen("in.txt", "r", stdin);
int T,n;
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
int k=0;
for(int i=1;i<=n;i++)
scanf("%d",&a[i]),k+=a[i],pre[i]=0;
if(k%n)
{
puts("-1");
continue;
}
k/=n;
int ans=0;
for(int i=1;i<=n;i++)
{
int have=pre[i]+a[i],res=0;
if(pre[i]<0) res=-pre[i];
if(have>k)
{
res+=have-k;
pre[i+1]=have-k;
}
else if(have<k)
pre[i+1]=have-k;
ans=max(res,ans);
}
printf("%d\n",ans);
}
return 0;
}
D:又是一道简单题
F:容斥+二分。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll INF=1e12;
int n,k,vis[17];
ll t[17],a[17];
typedef vector<ll> vll;
vll b[17];
ll gcd(ll a,ll b ){ return a%b?gcd(b,a%b):b; }
void build(int d, int p, int cur)
{
if(d==p)
{
ll res=1;
for(int i=0;i<d;i++)
{
ll gd=gcd(res,t[i]);
res=res*t[i]/gd;
if(res>INF) return;
}
b[d].push_back(res);
return ;
}
for(int i=cur;i<n;++i)
{
if(vis[i]) continue;
vis[i]=1;t[p]=a[i];
build(d,p+1,i+1);
vis[i]=0;
}
}
bool check(ll m)
{
ll res=0;
int f=1;
for(int i=1;i<=n;i++)
{
ll tmp=0;
for(auto v:b[i])
tmp+=m/v;
res+=f*tmp;
f=-f;
}
return res>=k;
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&k);
for(int i=1;i<=n;i++) b[i].clear();
for(int i=0;i<n;i++) scanf("%lld",&a[i]);
for(int i=1;i<=n;i++)
build(i,0,0);
ll l=1,r=1e12;
while(l<r)
{
ll m=(l+r)>>1;
if(check(m)) r=m;
else l=m+1;
}
printf("%lld\n",r);
}
return 0;
}