当前位置 : 主页 > 编程语言 > c语言 >

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

来源:互联网 收集:自由互联 发布时间:2023-09-03
A. Arcade Game time limit per test memory limit per test input output n which 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. n . The number n flies in th


A. Arcade Game



time limit per test



memory limit per test



input



output


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.

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



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


Output



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


Examples



input



3 952 925 592



output



0.000000000 0.166666667 0.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



memory limit per test



input



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:



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


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

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



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 12).



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



1 4 1 3 1 5 2 2 8 1 2 3 4 5 6 7 8



output



0 0 0 0 1 1 2 2



Note



In the sample test case:

At time 0: water is at node 1

(1, 2), and 1 unit of edge (1, 3)

(1, 2). The rate of melting of (1, 3) drops to 0.5 unit/second, while edge (2, 4)

(2, 4), and the remaining edge (1, 3)

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;  
}



上一篇:最大m子段和总结与例题 51nod1052 HDU1024
下一篇:没有了
网友评论