ACM暑假训练codeforces A. Arcade Game D. Frozen Rivers(康托展开式,spfa)

来源:互联网 发布:数据库基础知识总结 编辑:程序博客网 时间:2024/06/06 00:25
A. Arcade Game
time limit per test
1.0 s
memory limit per test
1024 MB
input
standard input
output
standard output

Arcade mall is a new modern mall. It has a new hammer game called "Arcade Game". In this game you're presented with a number nwhich is hanged on a wall on top of a long vertical tube, at the bottom of the tube there is a button that you should hit with your hammer.

When you hit the button with all your force (as you always do), a ball is pushed all over the tube and hit the number n. The number nflies in the air and it's digits fall back in any random permutation with uniform probability.

If the new number formed is less than or equal to the previous number, the game ends and you lose what ever the new number is. Otherwise (if the number is greater than the previous number), you are still in the game and you should hit the button again.

You win if the new number formed is greater than the previous number and it is equal to the greatest possible permutation number.

Can you compute the probability of winning?

Input

The first line of the input contains the number of test cases T. Following that there are T lines represents T test cases. In each line, there is a single integer (1 ≤ n ≤ 109) the target number. The digits of n are all unique, which means that any 2 digits of n are different.

Output

For each test case, print one line containing the answer. Print the answer rounded to exactly 9 decimal digits.

Examples
input
3952925592
output
0.0000000000.1666666670.194444444
Note

In the first test case, the answer is 0 because 952 is greater than all 2,5 and 9 permutations so you can't win, whatever you do.

In the second test case, the answer is 0.166666667 because you may win by getting number 952 with probability 1/6.

In the third test case the answer is 0.194444444 because you may win by getting number 952 in round1 with probability 1/6 or you can win by getting number 925 in round 1 and then 952 in round 2 with probability 1/6 * 1/6.

【解析】:

题意,每变换一次全排列,胜利的方法是,递增的,并且最后一次必须是全排列最高项。

先用康托展开,算出输入的数字之后的全排列有多少种。

然后枚举。反正最后一项必选。

枚举选中间的一项、两项......

但是组合数C必须优化,才能保证不超时

【代码】:

#include <stdio.h>#include <iostream>  #include <algorithm> using namespace std;typedef long long ll;ll fac[120];double C(ll n,ll m,ll A){//A除m+1次 double ans=1;for(int i=1;i<=m;i++){ans*=n;ans/=i;ans/=A;n--;}return ans/A;}int main(){int T;fac[0]=1;for(ll i=1;i<=110;i++){fac[i]=fac[i-1]*i;//阶乘 }cin>>T;while(T--){char n[22];cin>>n;ll c=strlen(n);for(int i=0;i<c;i++)a[i]=n[i]-'0';ll A=fac[c];//全排列;int b[16];memcpy(b,a,sizeof(a));sort(b,b+c);int dex[16]={0};for(int i=0;i<c;i++){dex[b[i]]=i;}int permu=0;int vis[16]={0};for(int i=0;i<c;i++){int cc=0;for(int j=0;j<a[i];j++)if(vis[j])cc++;permu+=(dex[a[i]]-cc)*fac[c-i-1];vis[a[i]]=1;}permu=fac[c]-permu-1;//以上康托展开,求得后面的全排列个数 double ans=0;double r=1.0/A;if(permu>0)ans+=r;double s=C(permu-1,1,A);if(1<=permu-1)ans+=s;for(int i=2;i<=permu-1;i++){//ans+=pow(r,i+1)*C(permu-1,i);s=s*(permu-i)/i/A;ans+=s;// *r^i+1}printf("%.9lf\n",ans);}return 0;}


D. Frozen Rivers
time limit per test
10.0 s
memory limit per test
1024 MB
input
standard input
output
standard output

In winter, all small rivers of Al-Asi great river in Syria are frozen. But when spring comes back they start to melt. These small rivers are connected to each other exactly like a tree, each river (direct edge in the tree) has a value equal to the amount of ice in it.

Here is the tree of the sample test case:

When rivers start to melt, water starts to flow from node 1 (root of the tree) to any node that it can reach. When the water first reaches a node u, ice starts to melt in all its direct children edges at a rate of 1 unit per second. Once (u, v) edge completely melted, the rate of melting of all other edges that start from u will slow down to be 0.5 unit per second, while the other edges that start from v start melting with 1 unit per second.

Given the rivers tree, and a certain time, can you tell us how many leaves of the tree did the water reach? A leaf is a node that has no children.

Input

The first line contains T the number of test cases. For each test case, the first line contains N the number of nodes (2 ≤ N ≤ 100, 000). Followed by N - 1 lines, each line describes the nodes 2 to N. Each line will contain 2 integers Pi and Ci (1  ≤  Pi ≤ N) (0  ≤  Ci  ≤ 100,000) representing the parent of the i-th node (i starts from 2 here) and the amount of ice in the edge connecting the current node to its parent. Node 1 is the root of the tree. After that there is a line contains (1 ≤ Q ≤ 100, 000), the number of queries. Then Q lines contain the times of these queries in seconds (0 ≤  query time  ≤ 1012).

Output

Print one line for each query in each test case, this line should contain the number of leaves that the water reached at the time of the query.

Examples
input
141 31 52 2812345678
output
00001122
Note

In the sample test case:

At time 0: water is at node 1

At time 1: water has melted 1 unit of edge (1, 2), and 1 unit of edge (1, 3)

At time 3: water has completely melted edge (1, 2). The rate of melting of (1, 3) drops to 0.5 unit/second, while edge (2, 4) starts to melt at rate 1 unit/second.

At time 5: water has completely melted edge (2, 4), and the remaining edge (1, 3) has 4 units melted, 1 to go.

At time 7: Ice completely melted in all edges.


【解析】:

题意给出一棵树图,一个根节点。

用BFS思想,模拟河流流动。(最短路算法中spfa类似),得出每个节点的到达时间

然后筛选出叶子上的时间,排个序;

每当询问时,就二分查找。时间复杂度O(n*log n)

【代码】:

#include <stdio.h>#include <stdlib.h>  #include <string.h>  #include <iostream>  #include <algorithm> #include <queue> using namespace std;typedef long long ll;const ll INF=0x3f3f3f3f3f3f3f3f;struct edge{      int u,v,cost;    int next;}e[201000];  int head[110000];//链式前向星 bool leaf[110000];//标记叶子节点 ll dis[110000];//每个节点的到达时间 ll t[110000];//叶子上的时间 int spfa(){    dis[1]=0;    queue<int> q; //装起点    q.push(1);      while(!q.empty())      {          int u=q.front();          q.pop();        ll minlen=INF;        for(int i=head[u];i!=-1;i=e[i].next) //找最近的孩子节点         {            if(minlen>e[i].cost)            minlen=e[i].cost;        q.push(e[i].v);          }        for(int i=head[u];i!=-1;i=e[i].next)  //算时间         {              int v=e[i].v;            dis[v]=dis[u]+1*minlen+2*(e[i].cost-minlen);        }    }}  int main()  {ll T,n,Q,q;cin>>T;while(T--){cin>>n;        memset(head,-1,sizeof(head));         memset(leaf,true,sizeof(leaf));//都是叶子         int top=1;        for(int i=1;i<n;i++)//n条边的输入          {              int u,v,cost;            scanf("%d%d",&u,&cost);            top++;            leaf[u]=false;//不是叶子            e[i].u=u;              e[i].v=top;              e[i].cost=cost;                        e[i].next=head[u];//u->v              head[u]=i;        }         spfa(); //最短路算法求出每个节点的到达时间 top=0;    for(int i=1;i<=n;i++)//把叶子时间挑出来排序,然后二分查找出答案     {    if(leaf[i])    t[top++]=dis[i];}sort(t,t+top);        cin>>Q;        while(Q--)//Q次询问         {cin>>q;int l=upper_bound(t,t+top,q)-t; cout<<l<<endl;}    }      return 0;  }  

原创粉丝点击