#多校赛2017#
As to a permutation p1,p2,⋯,pn from 1 to n, it is uncomplicated for each 1≤i≤n to calculate (li,ri) meeting the condition that min(pL,pL+1,⋯,pR)=pi if and only if li≤L≤i≤R≤ri for each 1≤L≤R≤n.
Given the positive integers n, (li,ri) (1≤i≤n), you are asked to calculate the number of possible permutations p1,p2,⋯,pn from 1 to n, meeting the above condition.
The answer may be very large, so you only need to give the value of answer modulo 109+7.
给n个L,R对,对于第i个对,表示其在(al, a(l+1),…ar)中为最小值,问有多少种(1…n)的置换满足条件。
不考虑数字的组合方式,对于给定的LR对生成的二叉树唯一,直接搜索即可。L升序R降序快排后发现,此时LR序列正好为二叉树的先序遍历结果!(贼关键)
#include
using namespace std;
typedef long long LL;
namespace fastIO {
#define BUF_SIZE 100000
//fread -> read
bool IOerror = 0;
inline char nc() {
static char buf[BUF_SIZE], *p1 = buf + BUF_SIZE, *pend = buf + BUF_SIZE;
if(p1 == pend) {
p1 = buf;
pend = buf + fread(buf, 1, BUF_SIZE, stdin);
if(pend == p1) {
IOerror = 1;
return -1;
}
}
return *p1++;
}
inline bool blank(char ch) {
return ch == ' ' || ch == '\n' || ch == '\r' || ch == '\t';
}
inline void read(int &x) {
char ch;
while(blank(ch = nc()));
if(IOerror)
return;
for(x = ch - '0'; (ch = nc()) >= '0' && ch <= '9'; x = x * 10 + ch - '0');
}
#undef BUF_SIZE
};
const int maxn = 1000005, mod = 1e9 + 7;
int fact[maxn], inv[maxn];
struct nd {
int a, b, pos;
bool operator < (const nd &_nd) const{
if(a == _nd.a) {
return b >= _nd.b;
}
return a < _nd.a;
}
} a[maxn];
int apos = 0;
int gg = 0;
int C(int n, int m) {
return (LL)fact[n] * (LL)inv[n-m] % mod * (LL)inv[m] % mod;
}
int solve(int l, int r) {
if(gg) return 0;
if(l > r) return 1;
if(a[apos].a != l || a[apos].b != r) {
gg = 1; return 0;
}
nd t = a[apos];
apos++;
if(l == r) return 1;
LL res = 1LL * C(t.b - t.a, t.pos - t.a) * solve(t.a,t.pos-1) % mod;
res = res * solve(t.pos + 1, t.b) % mod;
return (int)res;
}
int main() {
inv[1] = 1;
for(int i = 2; i < maxn; ++i)
inv[i] = mod - (int)(mod / i * (LL)inv[mod % i] % mod);
fact[0] = inv[0] = 1;
for(int i = 1; i < maxn; ++i)
{
fact[i] = (LL)fact[i - 1] * i % mod;
inv[i] = (LL)inv[i - 1] * inv[i] % mod;
}
int n, cs = 1;
while(fastIO::read(n), !fastIO::IOerror) {
for(int i = 0; i < n; i++) fastIO::read(a[i].a);
for(int i = 0; i < n; i++) {
fastIO::read(a[i].b);
a[i].pos = i + 1;
}
//LR对排序后的序列即是先序遍历结果
sort(a, a + n);
apos = gg = 0;
printf("Case #%d: %d\n",cs++,solve(1,n));
}
}
sd0061, the legend of Beihang University ACM-ICPC Team, retired last year leaving a group of noobs. Noobs have no idea how to deal with m coming contests. sd0061 has left a set of hints for them.
There are n noobs in the team, the i-th of which has a rating ai. sd0061 prepares one hint for each contest. The hint for the j-th contest is a number bj, which means that the noob with the (bj+1)-th lowest rating is ordained by sd0061 for the j-th contest.
The coach asks constroy to make a list of contestants. constroy looks into these hints and finds out: bi+bj≤bk is satisfied if bi≠bj, bi
给1e7个数,有100次查询,每次求第bi+1小的数,bi相当于斐波那契数列,这样就可以做到每次查询的范围缩小1.618倍,然后复杂度就是Sigma(n/1.618^i),其实就是求个等比数列。
会求复杂度就敢搞了。
#include
using namespace std;
typedef pair<int, int> p;
unsigned res[105];
unsigned x, y, z;
const int SIZE = 10000001;
unsigned aa[SIZE];
p ma[SIZE];
unsigned rng61() {
unsigned t;
x ^= x << 16;
x ^= x >> 5;
x ^= x << 1;
t = x;
x = y;
y = z;
z = t ^ x ^ y;
return z;
}
int main() {
int n, m, a, b, c;
int cs = 1;
while(~scanf("%d%d%d%d%d",&n,&m,&a,&b,&c)) {
x = a; y = b; z = c;
for(int i = 0; i < n; i++) aa[i] = rng61();
for(int i = 0; i < m; i++) {
scanf("%d",&ma[i].first);
ma[i].second = i;
}
sort(ma,ma + m);
ma[m] = p(n,n);
for(int i = m - 1; i >= 0; i--) {
nth_element(aa, aa + ma[i].first, aa + ma[i+1].first);
//
res[ma[i].second] = aa[ma[i].first];
}
printf("Case #%d:",cs++);
for(int i = 0; i < m; i++) printf(" %u",res[i]);
puts("");
}
return 0;
}
There is a connected undirected graph with weights on its edges. It is guaranteed that each edge appears in at most one simple cycle.
Assuming that the weight of a weighted spanning tree is the sum of weights on its edges, define V(k) as the weight of the k-th smallest weighted spanning tree of this graph, however, V(k) would be defined as zero if there did not exist k different weighted spanning trees.
Please calculate (∑k=1Kk⋅V(k))mod232.
仙人掌图,求1到k小的最小生成树权值和。
点双连通优先队列暴搞看脸A。
#include
#include
#include
#include
#include
using namespace std;
vector<int> res;
int K;
struct nd {
int w, x, y;
bool operator < (const nd& _nd) const {
return w < _nd.w;
}
};
vector<int> sv;
void Solve(vector<int> &va, vector<int> &vb) {
priority_queue pq;
for(int i = 0; i < vb.size(); i++) {
pq.push((nd) {va[0] + vb[i], 0, i});
}
sv.resize(0);
while(sv.size() < K && !pq.empty()) {
nd nt = pq.top(); pq.pop();
sv.push_back(nt.w);
if(nt.x + 1 < va.size()) {
nt.x ++;
pq.push((nd) {va[nt.x] + vb[nt.y], nt.x, nt.y});
}
}
va = sv;
}
const int MAXN = 1010;
const int MAXM = 5000;
struct Edge
{
int to,next,val;
} edge[MAXM];
int head[MAXN],tot;
int Low[MAXN],DFN[MAXN];//,Stack[MAXN],Belong[MAXN];
int Index,top;
int block;//点双连通分量的个数
//bool Instack[MAXN];
void addedge(int u,int v,int val)
{
edge[tot].to = v;edge[tot].next = head[u];edge[tot].val = val;head[u] = tot++;
}
stack<int> st;
void Tarjan(int u,int pre = -1)
{
int v;
Low[u] = DFN[u] = ++Index;
//Stack[top++] = u;
//Instack[u] = true;
for(int i = head[u];i != -1;i = edge[i].next)
{
v = edge[i].to;
//if(v == pre)continue;
if( !DFN[v] )
{
st.push(i);
Tarjan(v,u);
if(Low[u] > Low[v])Low[u] = Low[v];
if( Low[v] >= DFN[u])
{
block++;
int ii;
vector<int> t2;
do
{
//vn = Stack[--top];
//Belong[vn] = block;
//Instack[vn] = false;
ii = st.top();
st.pop();
t2.push_back(edge[ii].val);
}
while( ii!=i );
// cout << t2.size() << endl;
// for (auto &x : t2) cout << x << ' '; cout << endl;
if(t2.size() > 1) Solve(res, t2);
}
}
else if(v!=pre && DFN[v] < DFN[u]) {
st.push(i);
Low[u] = min(Low[u], DFN[v]);
}
// else if(Instack[v] && Low[u] > DFN[v])
// {
// Low[u] = DFN[v];
// st.push(i);
// }
}
}
void init()
{
tot = 0;
memset(head,-1,sizeof(head));
}
int main(){
//freopen("1009.in","r",stdin);
int n, m, cs = 1;
res.reserve(100005);
sv.reserve(100005);
while(~scanf("%d%d",&n,&m)) {
init();
int x, y, z;
int sum = 0;
for(int i = 1; i <= m; i++) {
scanf("%d%d%d",&x,&y,&z);
addedge(x,y,z);
addedge(y,x,z);
sum += z;
}
res.resize(0);
res.push_back(0);
scanf("%d",&K);
memset(DFN,0,sizeof(DFN));
//memset(Instack,false,sizeof(Instack));
//memset(Belong,0,sizeof(Belong));
Index = block = top = 0;
Tarjan(1);
unsigned r = 0;
for(int i = 0; i < res.size(); i++) {
r += (unsigned)(i + 1) * (unsigned)(sum - res[i]);
}
printf("Case #%d: %u\n",cs++,r);
//if(n == 28) return 0;
}
}