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
思路
可以直接根据题目给出的递推式把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;
}