SRM 545
250pt
题意:给定一组数,求这组数中是否存在一个数等于所有其它的数按位与(&)的值。
分析:因为a&b<=min(a,b)h和a&a=a,所以就是求这组数所有的数按位与之后的是否等于最小值。
View Code
class ANDEquation
{
public:
int restoreY(vector <int> A)
{
int i,m,k,n=A.size();
m=*max_element(A.begin(),A.end());
for(k=0,i=1;i<n;i++)
if(A[i]<A[k])
k=i;
for(i=0;i<n;i++)
if(i!=k)
m&=A[i];
return m==A[k]?m:-1;
}
};
550pt
题意:给定一个字符串S,minRev和n,求逆序数不小于minRev,字典序不小于S和由前n个小写字母组成的字符串T.
分析:因为字典序要大于S,所以考虑在补全S字符的基础上交换字母的位置来增加逆序数
如果s的字典序不小于minRev,那s就是答案。
否则贪心,对于长度为n的字母组成的字符串,逆序数最大为n*(n-1)/2;
因为要使T字典序最小,所以从要末尾开始修改,修改的位数越多,可增加的逆序数也越多。
PS.在类中自定义比较函数时要放到类外
View Code
int Cmp(char a,char b)
{
return a>b;
}
class StrIIRec
{
public:
string recovstr(int n, int minInv, string s)
{
int i,j,k,m,rev[22]={0};
bool used[22]={false};
m=(int)s.size();
for(i=0;i<m;i++)
used[s[i]-'a']=true;
for(i=0;i<n;i++)
if(!used[i])
s.push_back('a'+i);
for(i=n-2;i>=0;i--)
{
for(j=i+1;j<n;j++)
if(s[i]>s[j])
rev[i]++;
rev[i]+=rev[i+1];
}
m=rev[0];
if(m>=minInv)
return s;
for(i=n-2;i>=0;i--)
if(m-rev[i]+(n-i)*(n-i-1)/2>=minInv)
break;
k=minInv-m+rev[i]-(n-i-1)*(n-i-2)/2;
sort(s.begin()+i,s.end(),Cmp);
swap(s[i],s[n-1-k]);
sort(s.begin()+i+1,s.end(),Cmp);
return s;
}
};
1000pt
题意:给定一张长为L+1,高为H+1的网格图,求符合下列条件的集合有多少种
1,包含K个格点
2,K个点必须在一条直线上;
3,有且仅有一个点的高度为0;
分析:枚举步差步差来代表某个集合,用最大公约数判断是否是最小步差,即集合是否枚举过
PS:有O(L*H)算法,没看懂
View Code
#define MAX 1000000007
class SpacetskE
{
public:
int gcd(int a,int b)
{
return b?gcd(b,a%b):a;
}
int countsets(int L, int H, int K)
{
int i,j,n,m,a,b,x2,x1,y2;
int c[222][222]={0};
for(i=0;i<222;i++)
c[i][0]=c[i][i]=1;
for(i=2;i<222;i++)
for(j=1;j<=i;j++)
c[i][j]=(c[i-1][j-1]+c[i-1][j])%MAX;
if(K==1)
return (L+1)*(H+1);
for(m=i=0;i<=L;i++)
m=(m+c[H+1][K])%MAX;
for(x1=0;x1<=L;x1++)
for(x2=0;x2<=L;x2++)
if(x1!=x2)
for(y2=1;y2<=H;y2++)
{
a=abs(x2-x1);
b=y2;
if(gcd(a,b)>1)
continue;
if(x2>x1)
n=min((L-x1)/a,H/b);
else
n=min(x1/a,H/b);
n++;
if(K<=n)
m=(m+c[n][K])%MAX;
}
return m;
}
};
转载于:https://www.cnblogs.com/xchaos/archive/2012/06/15/2550486.html