链接:戳这里
DZY Loves Balls
Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 262144/262144 K (Java/Others)
问题描述
DZY喜欢玩球。
他有n个球,装进一个大盒子里。每个球上面都写着一个整数。
有一天他打算从盒子中挑两个球出来。他先均匀随机地从盒子中挑出一个球,记为A。他不把A放回盒子,然后再从盒子中均匀随机地挑出一个球,记为B。
如果A上的数字严格大于B上的数字,那么他就会感到愉悦。
现在告诉你每个球上的数字,请你求出他感到愉悦的概率是多少。
输入描述
第一行t,表示有t组数据。
接下来t组数据。每组数据中,第一行包含一个整数n,第二行包含n个用空格隔开的正整数ai,表示球上的数字。
(1≤t≤300,2≤n≤300,1≤ai≤300)
输出描述
对于每个数据,输出一个实数答案,保留6位小数。
输入样例
2
3
1 2 3
3
100 100 100
输出样例
0.500000
0.000000
思路:两个for暴力找出符合条件的个数
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<string>
#include<vector>
#include <ctime>
#include<queue>
#include<set>
#include<map>
#include<stack>
#include<cmath>
#define mst(ss,b) memset((ss),(b),sizeof(ss))
#define maxn 0x3f3f3f3f
#define MAX 1000100
///#pragma comment(linker, "/STACK:102400000,102400000")
typedef long long ll;
typedef unsigned long long ull;
#define INF (1ll<<60)-1
using namespace std;
int T,n;
int a[1001],b[1001];
int main(){
scanf("%d",&T);
while(T--){
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
}
int Y=n*(n-1);
int X=0;
for(int i=1;i<=n;i++){
int num=0;
for(int j=1;j<=n;j++){
if(i==j) continue;
if(a[i]>a[j]) num++;
}
X+=num;
}
double ans=(double)X*1.0/Y;
printf("%.6f\n",ans);
}
return 0;
}
DZY Loves Partition
Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 262144/262144 K (Java/Others)
问题描述
DZY喜欢拆分数字。他想知道能否把nn拆成恰好kk个不重复的正整数之和。
思考了一会儿之后他发现这个题太简单,于是他想要最大化这k个正整数的乘积。你能帮帮他吗?
由于答案可能很大,请模10^9+7输出。
输入描述
第一行t,表示有t组数据。
接下来tt组数据。每组数据包含一行两个正整数n,k。
(1≤t≤50,2≤n,k≤10e9)
输出描述
对于每个数据,如果不存在拆分方案,输出-1−1;否则输出最大乘积模10^9 + 7之后的值。
输入样例
4
3 4
3 2
9 3
666666 2
输出样例
-1
2
24
110888111
Hint
第一组数据没有合法拆分方案。
第二组数据方案为3=1+2,答案为1×2=2
第三组数据方案为9=2+3+4,答案为2×3×4=24。注意9=3+3+3是不合法的拆分方案,因为其中包含了重复数字。
第四组数据方案为666666=333332+333334,答案为333332×333334=111110888888。注意要对10^9 + 7取模后输出。
思路:首先肯定的是连续的数乘积肯定最大,那么我们先判断sum(1,k)是否大于n
填充完了连续的k个数之后,处理多出的值得情况,其实这里已经很明显了,直接从后往前累加1
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<string>
#include<vector>
#include <ctime>
#include<queue>
#include<set>
#include<map>
#include<stack>
#include<cmath>
#define mst(ss,b) memset((ss),(b),sizeof(ss))
#define maxn 0x3f3f3f3f
#define MAX 1000100
///#pragma comment(linker, "/STACK:102400000,102400000")
typedef long long ll;
typedef unsigned long long ull;
#define INF (1ll<<60)-1
using namespace std;
int T,n;
int a[1001],b[1001];
int main(){
scanf("%d",&T);
while(T--){
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
}
int Y=n*(n-1);
int X=0;
for(int i=1;i<=n;i++){
int num=0;
for(int j=1;j<=n;j++){
if(i==j) continue;
if(a[i]>a[j]) num++;
}
X+=num;
}
double ans=(double)X*1.0/Y;
printf("%.6f\n",ans);
}
return 0;
}
DZY Loves Connecting
Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 262144/262144 K (Java/Others)
问题描述
DZY有一棵n个结点的无根树,结点按照1∼n标号。
DZY喜欢树上的连通集。一个连通集S是由一些结点组成的集合,满足SS中任意两个结点u,v能够用树上的路径连通,且路径上不经过S之外的结点。显然,单独一个结点的集合也是连通集。
一个连通集的大小定义为它包含的结点个数,DZY想知道所有连通集的大小之和是多少。你能帮他数一数吗?
答案可能很大,请对10^9 + 7取模后输出。
输入描述
第一行t,表示有t组数据。
接下来tt组数据。每组数据第1行一个数n。第2∼n行中,第i行包含一个数pi,表示i与pi有边相连。(1≤pi ≤i−1,2≤i≤n)
(n≥1,所有数据中的n之和不超过200000)
输出描述
每组数据输出一行答案,对10^9 + 7取模。
输入样例
2
1
5
1
2
2
3
输出样例
1
42
Hint
第二个样例中,树的4条边分别为(1,2),(2,3),(2,4),(3,5)。所有连通集分别是{1},{2},{3},{4},{5},{1,2},{2,3},{2,4},{3,5},{1,2,3},{1,2,4},{2,3,4},{2,3,5},{1,2,3,4},{1,2,3,5},{2,3,4,5},{1,2,3,4,5}。
If you need a larger stack size,
please use #pragma comment(linker, "/STACK:102400000,102400000") and submit your solution using C++.
Statistic | Submit | Clarifications | Back
思路:我们设定两个数组 val[i]和num[i] 分别代表当前节点的贡献,儿子数
计算当前的值贡献 val[i]=val[i]+val[i]*num[j]+val[j]*num[i]
这段代码的意思是在树上,当前节点的贡献值等于它的儿子的贡献乘以父亲原有的儿子+当前父亲的贡献乘以儿子的儿子数,似乎很难理解 那我就不说了
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<string>
#include<vector>
#include <ctime>
#include<queue>
#include<set>
#include<map>
#include<stack>
#include<cmath>
#define mst(ss,b) memset((ss),(b),sizeof(ss))
#define maxn 0x3f3f3f3f
#define MAX 1000100
///#pragma comment(linker, "/STACK:102400000,102400000")
typedef long long ll;
typedef unsigned long long ull;
#define INF (1ll<<60)-1
#define mod 1000000007
using namespace std;
int T,n;
struct edge{
int u,v,next;
}e[2000100];
int head[200010],tot;
ll val[200010],num[200010];
void init(){
mst(head,-1);
tot=0;
for(int i=1;i<=n;i++) val[i]=num[i]=1;
}
void add(int u,int v){
e[tot].u=u;
e[tot].v=v;
e[tot].next=head[u];
head[u]=tot++;
}
void DFS(int u,int fa){
for(int i=head[u];i!=-1;i=e[i].next){
int v=e[i].v;
if(v==fa) continue;
DFS(v,u);
val[u]=(val[u]+val[u]*num[v]+val[v]*num[u])%mod;
num[u]=num[u]*(num[v]+1)%mod;
}
}
int main(){
scanf("%d",&T);
while(T--){
scanf("%d",&n);
init();
for(int i=2;i<=n;i++){
int x;
scanf("%d",&x);
add(i,x);
add(x,i);
}
DFS(1,0);
ll ans=0;
for(int i=1;i<=n;i++){
ans+=val[i];
ans%=mod;
}
printf("%I64d\n",ans);
}
return 0;
}