TopCoder SRM 569

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_40032278/article/details/82145327

div.1

T1

题意

有一台机器,给定两个长度为N的01串作为输入,分别对每一位进行与、或、异或中的一种操作,输出操作后的串。先给定M个01串,问至少要添加几个串,才能判断出机器对每一位分别进行什么操作。

思路

显然位与位之间互相独立,那么单独考虑一位。
对于每一位,都至少要有1个0,2个1,如果不足就要添加。
这是只有三种输入:(0,0),(0,1),(1,1)。能区别AND和OR的有(0,1);能区别AND和XOR的有(0,1)和(1,1);能区别OR和XOR的有(1,1)。只要分别统计M个串中每一位0和1的个数,再判断一下即可。答案不会超过2。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

class TheDevice {
public:
    int minimumAdditional( vector <string> plates );
};
int TheDevice::minimumAdditional(vector <string> a) {
    int n,m,ans,i,j,x,y,z;
    n=a.size();
    m=a[0].size();
    ans=0;
    for(j=0;j<m;j++)
    {
        x=0;
        y=0;
        z=0;
        for(i=0;i<n;i++)
            if(a[i][j]=='0') x++;
            else y++;
        if(x==0) z++;
        if(y<2) z=z+2-x;
        ans=max(ans,z);
    }
    return ans;
}

T2

题意

一栋大楼共N层(0~N-1),第i层有a[i]个人。每层都要分配a[i]/k取上整个城管来管这些人。第i层楼的人可以在第i层、i+1层或者i-1层中的某一层楼,求最少需要几个城管来管所有人。

思路

如果某一层的人数不是K的整数倍,那么我们可以将上下层多出的人移到该层。考虑第i-1、i和i+1层之间的关系。i-1->1和i+1->i可以视为i->i-1和i+1->i-1。假设只有i和i-1,那么双向的移动是等价的。三层楼之间互相影响只有上下两层都集中的一层这种情况(这和一层分散到两层是等价的),也与i+1->i-1等价。
那么就有这样一个贪心策略:从0层开始,计算0层需要几个城管,以及0层还能移入几个人,即为rem,然后从1层往0层移不超过rem的尽量多的人。如果此时移入的人还不超过rem(也即1层的人数少于rem),就从2层继续移。之后把1层视为新的0层,再重新开始。

#include <bits/stdc++.h>
using namespace std;
int n,c[100];

class TheJediTest {
public:
    int minimumSupervisors( vector <int> students, int K );
};
int sol(int x,int k)
{
    return x%k?x/k+1:x/k;
}
int TheJediTest::minimumSupervisors(vector <int> a, int k) {
    n=a.size();
    int ans=2e9,i,j,s,d,x;
    for(i=0;i<1<<(n-1);i++)
    {
        s=0;
        for(j=0;j<n;j++) c[j]=a[j];
        for(j=0;j<n-1;j++)
        {
            d=c[j]%k;
            if(i&(1<<j))
            {
                x=min(a[j],d);
                c[j]=c[j]-x;
                c[j+1]=c[j+1]+x;
            }
            else 
            {
                d=k-d;
                if(d==k) d=0;
                x=min(a[j+1],d);
                c[j]=c[j]+x;
                c[j+1]=c[j+1]-x;
            }
            s=s+sol(c[j],k);
        }
        s=s+sol(c[n-1],k);
        ans=min(ans,s);
    }
    return ans;
}

div.2

T3

题意

n!k = n!(k-1) * (n-1)!k
0!k = 1
n!0 = n
求n!k

思路

扫描二维码关注公众号,回复: 2967528 查看本文章

可以直接根据题目给出的递推式把n!k个各个质因子个数递推出来(不过空间开不下要用滚动数组)
求因子个数有个公式相信大家小学就知道了
若x=p1^a1⋅p2^a2⋯pm^am,其中p1,p2,⋯,pm为质数
则x的因子个数为a1⋅a2⋯am
就相当于对每个质因子pi可以选[0,ai]次,共有ai+1种选法,根据乘法原理乘起来就行了。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod=1e9+9;
int vis[10010],p[10010],cnt;
ll d[2][1010][1010];

class MegaFactorialDiv2 {
public:
    int countDivisors( int N, int K );
};
int MegaFactorialDiv2::countDivisors(int n, int k) {
    int i,j,s=0,x,l;
    cnt=0;
    memset(d,0,sizeof(d));
    memset(vis,0,sizeof(vis));
    for(i=2;i<=1000;i++)
    {
        if(vis[i]==0) p[++cnt]=i;
        for(j=1;j<=cnt&&i*p[j]<=1000;j++)
        {
            vis[i*p[j]]=1;
            if(i%p[j]==0) break;
        }
    }
    for(i=1;i<=n;i++)
    {
        s=s^1;
        memset(d[s],0,sizeof(d[s]));
        x=i;
        for(j=1;j<=cnt;j++)
            while(x%p[j]==0)
            {
                x=x/p[j];
                d[s][0][j]++;
            }
        for(j=1;j<=k;j++)
            for(l=1;l<=cnt;l++)
                d[s][j][l]=(d[s^1][j][l]+d[s][j-1][l])%mod;
    }
    ll ans=1;
    for(i=1;i<=cnt;i++)
     ans=ans*(d[s][k][i]+1)%mod;
    return (int)ans%mod;
}

猜你喜欢

转载自blog.csdn.net/qq_40032278/article/details/82145327
今日推荐