代码改变世界

srm 545 div1

2012-06-09 03:25  macaroniz  阅读(229)  评论(0)    收藏  举报

250pt

从最高位(左边)开始考虑,从小到大枚举当前位可能的数字,判断是否有可能构造出结果,如果有可能就把当前数字固定下来,考虑下一位数字。整体思想类似按位dp。

using namespace std;
class StrIIRec
{
public:
    string ans,minStr;
    int hash[30];
    int n;

    int maybe(char ch)
    {
        string str = ans + ch;
        for(int i = n-1;i >= 0;i--)
            if(hash[i] == 0 && i != ch-'a')
                str += 'a' + i;
        int ret = 0;
        for(int i = 0;i < n;i++)
            for(int j = 0;j < i;j++)
                if(str[i] < str[j]) ret++;
        return ret;
    }

    string recovstr(int _n, int minInv, string _minStr)
    {
        ans="";
        minStr = _minStr;
        n = _n;
        bool FSame = true;
        memset(hash,0,sizeof hash);
        for(int i = 0;i < n;i++)
        {
            for(char ch = 'a';ch < 'a' + n;ch++)
            {
                if((!FSame || ch >= minStr[i]) && hash[ch - 'a'] == 0 && maybe(ch) >= minInv)
                {
                    ans += ch;
                    hash[ch -'a'] = 1;
                    if(ch > minStr[i]) FSame = false;
                    break;
                }
            }
            if(ans.length() != i+1) return "";
        }
        return ans;
    }
};

500pt

思路大概是固定一个端点在(0,0)点,然后计算该情况下的可能性,其他的情况通过平移得到,但是可以直接算出。

基本上是纯数学题,细节看代码吧,比较繁琐。

int C[2010][2010];
class Spacetsk
{
public:
    int gcd(int a,int b)
    {
        if(b == 0) return a;
        else return gcd(b,a % b);
    }

    int calc(int x,int y,int L,int H,int K)
    {
        int _gcd = gcd(x,y);
        int gx = x / _gcd,gy = y / _gcd;
        int kmax = x / gx + 1;
        if(kmax > y / gy + 1) kmax = y/gy + 1;
        if(kmax < K) return 0;
        return (1ll*C[kmax-1][K-1] * (L - x + 1)) % 1000000007;
    }
    int countsets(int L, int H, int K)
    {
        memset(C,0,sizeof C);
        C[0][0] = 1;
        for(int i = 1;i <= 2005;i++)
        {
            C[i][0] = 1;
            for(int j = 1;j <= i;j++)
                C[i][j] = (C[i-1][j]+C[i-1][j-1]) % 1000000007;
        }
        int ans = 0;
        if(H + 1 >= K) ans= (ans + (1ll*(L+1)*C[H + 1][K] % 1000000007)) % 1000000007;
        if(K == 1)
            return (L+1) * (H+1) % 1000000007;
        for(int i = 1;i <= L;i++)
            for(int j = 1;j <= H;j++)
            {
                ans = (ans + (2*calc(i,j,L,H,K)) % 1000000007) % 1000000007;
            }
        return ans;
    }
};

975pt