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
浙公网安备 33010602011771号