Discription:
There is an old country and the king fell in love with a devil. The devil always ask the king to do some crazy things. Although the king used to be wise and beloved by his people. Now he is just like a boy in love and can’t refuse any request from the devil. Also, this devil is looking like a very cute Loli.
Something bad actually happen. The devil makes this kingdom's people infected by a disease called lolicon. Lolicon will take away people's life in silence.
Although z*p is died, his friend, y*wan is not a lolicon. Y*wan is the only one in the country who is immune of lolicon, because he like the adult one so much.
As this country is going to hell, y*wan want to save this country from lolicon, so he starts his journey.
You heard about it and want to help y*wan, but y*wan questioned your IQ, and give you a question, so you should solve it to prove your IQ is high enough.
The problem is about counting. How many undirected graphs satisfied the following constraints?
1. This graph is a complete graph of size n.
2. Every edge has integer cost from 1 to L.
3. The cost of the shortest path from 1 to n is k.
Can you solve it?
output the answer modulo 10^9+7
Something bad actually happen. The devil makes this kingdom's people infected by a disease called lolicon. Lolicon will take away people's life in silence.
Although z*p is died, his friend, y*wan is not a lolicon. Y*wan is the only one in the country who is immune of lolicon, because he like the adult one so much.
As this country is going to hell, y*wan want to save this country from lolicon, so he starts his journey.
You heard about it and want to help y*wan, but y*wan questioned your IQ, and give you a question, so you should solve it to prove your IQ is high enough.
The problem is about counting. How many undirected graphs satisfied the following constraints?
1. This graph is a complete graph of size n.
2. Every edge has integer cost from 1 to L.
3. The cost of the shortest path from 1 to n is k.
Can you solve it?
output the answer modulo 10^9+7
Input
The first line contains an integer T, denoting the number of the test cases.
For each test case, the first line contains 3 integers n,k,L.
T<=5 n,k<=12,L<=10^9.
Output
For each test case, output the answer in one line.
Sample Input
2
3 3 3
4 4 4
Sample Output
8 668
陈立杰大神出的题,想了想又写了写2h就过去了orz
题目大意就是给出n,k,L ,问有多少n个点的带标号的完全无向图,
满足1-n的最短路长度为k,且每条边的权值都>=1且<=L 。
(要不是上午ZHW点拨了几下我估计一晚上都做不出来hhh)
首先不能枚举最短路的构成,这样显然会挂掉,因为1-n可能会有很多条最短的路径;
然后考虑一下枚举每一个dis[i],代表1号节点到i号节点的最短路长度。
假设我们不用管枚举dis的时间花费,先关注一下如果dis都确定了的话如何更新答案。
先把dis从小到大排序,之后从后面的点向前面的每个节点连边(这样才能是完全图嘛。。)。
边权显然不是任意的,可以发现的是如果1到i(代表最短路长度从小到大排序后第i小点)
的最短路长度为dis[i]的话,必须满足:
1.对于所有的dis[j]<dis[i],
使得dis[j]+val(j,i)>=dis[i]
2.存在dis[j]<dis[i],
使得dis[j]+val(j,i)==dis[i]
满足上两个条件的方案数不难求,一个容斥就ojbk了。
然后再考虑dis[j]==dis[i]的点j,发现边权是多少都无所谓,所以都×L就行了。
但是可能会有点的dis>k,这可怎么办呢?
这样就设dis[i]==k(这里i!=n)的意思为1到i的最短路长度>=k,
那么我们统计这类节点的方案数就不用容斥减去了,直接乘上满足条件1的方案数就行了。
但是搜索出每个dis[i]的值是会TLE的,需要考虑一种更加高效的方法。
其实我们不必知道每个dis是多少,只需要知道对于1<=x<=k的每个x,dis[i]==x的i有多少个就行了。
这样我们改变搜索对象(实验证明这样搜索能到达的状态最多有10^5种,再乘上n^2的更新答案时间根本不虚),
中间计算的时候乘上组合数就行了(相当于算等于x的dis[i]分别对应原图中的哪些节点)
#include<iostream> #include<cstdio> #include<cmath> #include<cstdlib> #include<algorithm> #include<map> #include<cstring> #define ll long long #define ha 1000000007 using namespace std; ll n,k,L,T,ans; ll C[105][105],jc[105]; ll num[105],cnt=0; ll ci[105][105]; inline void init(){ C[0][0]=jc[0]=1; for(int i=1;i<=30;i++){ C[i][0]=1,jc[i]=jc[i-1]*(ll)i%ha; for(int j=1;j<=i;j++){ C[i][j]=C[i-1][j-1]+C[i-1][j]; if(C[i][j]>=ha) C[i][j]-=ha; } } } inline ll calc(){ ll an=1,rk1,rk2,fin=num[k]; num[k]=1; //先算num<k和num==k中的n的情况。 for(int i=1;i<=k;i++) if(num[i]){ rk1=rk2=1; for(int j=0;j<i;j++) if(num[j]){ rk1=rk1*ci[i-j-1][num[j]]; rk2=rk2*ci[i-j][num[j]]; if(rk1>=ha) rk1-=rk1/ha*ha; if(rk2>=ha) rk2-=rk2/ha*ha; } rk1+=ha-rk2; if(rk1>=ha) rk1-=ha; for(int j=1;j<=num[i];j++){ an=an*rk1; rk1=rk1*L; if(an>=ha) an-=an/ha*ha; if(rk1>=ha) rk1-=rk1/ha*ha; } } //再求num==k的其他点的方案数 num[k]=fin-1; if(num[k]){ rk1=1; for(int i=0;i<k;i++) if(num[i]){ rk1=rk1*ci[k-i-1][num[i]]; if(rk1>=ha) rk1-=rk1/ha*ha; } for(int j=1;j<=num[k];j++){ rk1=rk1*L; if(rk1>=ha) rk1-=rk1/ha*ha; an=an*rk1; if(an>=ha) an-=an/ha*ha; } } return an; } void dfs(int tmp,int lef,ll alr){ if(tmp==k-1){ num[k]=lef+1; ans+=alr*calc()%ha; if(ans>=ha) ans-=ha; return; } for(int u=0;u<=lef;u++){ ll to=alr*C[lef][u]%ha; num[tmp+1]=u; dfs(tmp+1,lef-u,to); } } inline void solve(){ dfs(0,n,1); } int main(){ init(); scanf("%lld",&T); while(T--){ ans=0; memset(num,0,sizeof(num)); memset(ci,0,sizeof(ci)); scanf("%lld%lld%lld",&n,&k,&L); if(L<k){ puts("0"); continue; } for(int i=0;i<=k;i++){ ci[i][0]=1; for(int j=1;j<=n;j++) ci[i][j]=ci[i][j-1]*(L-i+ha)%ha; } n-=2,num[0]=num[k]=1,solve(); printf("%lld ",ans); } return 0; }