分数统计
【PrayerOJ-4950】
【题目描述】
在统计完朋友情况之后,小明又对大家的毕业学校产生兴趣,但是他觉得单纯的统计人数是一件非常无聊的事情,于是他设计了一个算法,同一所学校毕业的学生,第1个将获得1 分,第2个获得2分,第3个获得4分…,第i个将获得2i-1分,总分就是这所小学的得分,小明想知道得分最高的学校有多少分。
【输入】
输入文件score.in的第一行有两个整数n和m,n表示总人数,m表示已知的同校关系数量。
接下来n行,每行有2个以空格隔开的整数a和b,表示a和b是来自同一所学校,a和b均为1到n之间的整数。不会给出重复的信息。
【输出】
输出文件 score.out 只有一行,为所有学校中的最高得分。最后得分可能会很大,你只需要输出后 100 位即可,不足 100 位的请直接输出。
【样例输入】
5 3
1 2
3 4
1 3
【样例输出】
15
【样例说明】
1、2、3、4来自同一所学校,该所学校所得的分数为1+2+4+8=15
【数据规模】
60%的数据,1 <= n <= 10
80%的数据,1 <= n <= 70
100%的数据,1 <= n <= 10000,1 <= m <= 100000
【代码】
#include <iostream> #include <cstdio> #include <cstdlib> #include <cmath> #include <cstring> #include <algorithm> #define RI register int #define re(i,a,b) for(RI i=a; i<=b; i++) #define ms(i,a) memset(a,i,sizeof(a)) using namespace std; typedef long long LL; int const N=10005; int n,m; int f[N],s[N]; struct bignum { int l,x[105]; void init(int v) { l=0; ms(0,x); while(v) { x[++l]=v%10; v/=10; } } }; int find(int x) { return x==f[x] ? x:f[x]=find(f[x]); } bignum cf(bignum a) { bignum c; c.init(0); re(i,1,a.l) { c.x[i]=a.x[i]*2+c.x[i-1]/10; c.x[i-1]%=10; } c.l=a.l; while(c.x[c.l]>9) { c.l++; c.x[c.l]=c.x[c.l-1]/10; c.x[c.l-1]%=10; } if(c.l>100) c.l=100; return c; } int main() { scanf("%d%d",&n,&m); re(i,1,n) f[i]=i,s[i]=1; int num=1; while(m--) { int x,y; scanf("%d%d",&x,&y); int fx=find(x); int fy=find(y); if(fx!=fy) { f[fx]=fy; s[fy]+=s[fx]; num=max(num,s[fy]); } } bignum ans; ans.init(1); re(i,1,num) ans=cf(ans); ans.x[1]--; for(int i=ans.l; i>=1; i--) printf("%d",ans.x[i]); return 0; }