您的位置:首页 > 其它

codeforces 428(div2) A-D

2017-08-17 18:06 363 查看
A题:签到

B题思维。

这个不能除8,不能把一个军队中的8个放在一行,因为有可能不放在一行更优,如:

2 5

8 2 2 2 2

将8分成4 4放在第一行和第二行中的中间4个,就可以放的下了。

先排序从大到小

//如果有4的话就先填中间的,如果3的话也填中间的,

//如果是2的话,先填两边的,如果两边填完了就填中间的余下1

//如果是1的话,先填中间的,如果中间的满了,就填两边的。

#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <cstdio>

using namespace std;
const int maxn=  1e5+10;
int a[maxn];
bool cmp(int a1,int b1)
{
return a1>b1;
}
int main()
{
int n,k;
scanf("%d %d",&n,&k);
for(int i=0;i<k;i++)
scanf("%d",&a[i]);
int c1=n,c2=n*2,c3=0,flag=0;
sort(a,a+k,cmp);
for(int i=0;i<k;i++)
{
while(a[i]>=4&&c1)
{
c1--;
a[i]-=4;
}
while(a[i]>=3&&c1)
{
c1--;
a[i]-=3;
}
while(a[i]>=2&&c2)
{
c2--;
a[i]-=2;
}
while(a[i]>=2&&c1)
{
c1--;
c3++;
a[i]-=2;
}
while(a[i]>=1&&c3)
{
c3--;
a[i]-=1;
}
while(a[i]>=1&&c1)
{
c1--;c2++;
a[i]-=1;
}
while(a[i]>=1&&c2)
{
c2--;
a[i]-=1;
}
if(a[i]>0) {
printf("NO\n");
flag=1;
break;
}
}
if(!flag) printf("YES\n");
return 0;
}


C题:就是一个dfs,注意这里每个叶子节点的概率是不一样的。

D题:

题意:给你n个数a1,a2,a3…an,k=gcd(ai,ai+1,…aj)>1;

问 全部的k*(j-i+1)是多少。

因为我们要求所有的gcd*长度,相同gcd可以一起算,所以我们要知道gcd=k有多个。

可以求出gcd=k的倍数(倍数>=1)有多少个,就是v∗2v−1(v为数组中k的倍数的个数),然后容斥一下。

怎么容斥?和之前一样,先把gcd=k的倍数的值都算出来,然后容斥

//这种容斥会超时//枚举倍数去找因子
for(int i=maxx;i>1;i--)//从后往前减
{
for(int j=2;j<i;j++)//从前往后,看谁是i的因子
{
if(i%j==0)
ans[j]=(ans[j]-ans[i]+inf)%inf;
}
}
//应该这样容斥枚举因子去找倍数
for(int i=maxx;i>1;i--)
{
for(int j=i+i;j<=maxx;j+=i)
{
ans[i]=(ans[i]-ans[j]+inf)%inf;
}
}


还可以用莫比乌斯反演来做

先推公式

ans=∑maxd=2d∗∑k∗gcd(a1,a2,...ak) 其中gcd(a1,a2,…ak)=d;

令f(x)=∑k∗gcd(a1,a2,...ak) 也就是gcd=d的时候的贡献

F(x):gcd=d的倍数的时候的贡献。

因为F(x)很好求,为V*2v−1

F(x)=∑x|df(d)

反演后可得

f(x)=∑x|dμ(d/x)∗F[d]

ans=∑maxd=2d∗f(d)

所以我们把f(d)算出来就行了

#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <cstdio>

using namespace std;
const int maxn= 1e6+10;
#define inf 1000000007
#define LL long long
int a[maxn];
LL ans[maxn],b[maxn],miu[maxn],primes[maxn],F[maxn];
int vis[maxn];
void mobious()
{
miu[1]=1;
int tot=0;
for(LL i=2;i<=1000000;i++)
{
if(!vis[i])
{
primes[tot++]=i;
miu[i]=-1;
}
for(LL j=0;j<tot;j++)
{
long long k=i*primes[j];
if(k>1000000) break;
vis[k]=1;
if(i%primes[j]) miu[k]=-miu[i];
else break;
}
}
}

int main()
{
int n,maxx=0;
mobious();
scanf("%d",&n);
for(int i=0;i<n;i++)
{
int x;
scanf("%d",&x);
a[x]++;
if(x>maxx) maxx=x;
}
b[0]=1;
for(int i=1;i<=maxx;i++)
b[i]=(b[i-1]<<1)%inf;
for(int i=2;i<=maxx;i++)
{
//if(!a[i]) continue;//注意这里不能加
LL t=0;
for(int j=i;j<=maxx;j+=i)
{
if(a[j]) t+=a[j];
}
F[i]=t*b[t-1]%inf;
}
LL total=0;
for(LL i=2;i<=maxx;i++)
{
LL sum=0;
if(!F[i]) continue;
for(int j=i;j<=maxx;j+=i)
{
sum=(sum+miu[j/i]*F[j])%inf;
if(sum<0) sum=sum+inf;
}
total=(total+sum*i%inf)%inf;
}
printf("%I64d\n",total%inf);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: