Gym 100338H High Speed Trains(高精度)
来源:互联网 发布:ios禁止软件联网 编辑:程序博客网 时间:2024/04/30 06:55
Gym 100338H High Speed Trains
题意:
求n个城市相互连通的方案数。
思路:
和HDU 4390迷之相似。
一共有n个城市,那么就有
答案 = 所有 - 一个城市独立的情况 - 两个城市独立的情况 - … - n-2个城市独立的情况 - 0个城市独立的情况(不可能有一个城市独立啦
但是这题数据不要求模除。。
打表的长度大概是50KB,超过了提交代码最大30KB的限制;
所以要动用高精度,用C++的高精度很浪费,因为ans数组与组合数都需要高精度才能存下,但前者最多几十位,后者n=100的时候大概上千位,而一般高精度的模板是不支持动态修改数组长度的。。所以很容易MLE,虽然通过修改重载函数可以办到,但是还是麻烦啊!
高精度Java写起来可以简化不少,但这题又有个巨坑。。就是要用文件重定向输入输出,臣妾做不到啊。。虽然后来发现就是几行代码的事
当然啦,直接用python的话,好像可以秒杀吧?
代码:
C++,Java,python都写了一份,看个人喜好吧。
C++:
#include<cstdio>#include<cstring>#include<cmath>#include<cstdlib>#include<iostream>#include<algorithm>#include<vector>#include<map>#include<queue>#include<stack>#include<string>#include<map>#include<set>#define eps 1e-6using namespace std;typedef long long lint;typedef long long ll;typedef long long LL;const int maxn = 2000;const int maxm = 50;struct bign1{ int len, s[maxm]; bign1()//构造函数 { memset(s, 0, sizeof(s)); len = 1; } bign1 operator = (const char * num) { len = strlen(num); for (int i = 0; i < len; i++) s[i] = num[len - i - 1] - '0'; return *this; } bign1(const char * num){ *this = num; }//支持初始化操作 bign1 operator = (int num) { char s[maxm]; sprintf(s, "%d", num);//把num输出到字符串s中 *this = s; return *this; } bign1(int num){ *this = num; } string str() const //利用string类把字符串数组转换为字符串,方便用<<,>>输出 { string res = ""; for (int i = 0; i < len; i++) res = (char)(s[i] + '0') + res; if (res == "") res = "0"; return res; } bign1 operator + (const bign1& b) const//定义加法 { bign1 c; c.len = 0; for (int i = 0, g = 0; g || i < max(len, b.len); i++)//要两个数的位数都计算一便 { int x = g;//g为其余数 if (i < len) x += s[i]; if (i < b.len) x += b.s[i]; c.s[c.len++] = x % 10; g = x / 10; } return c; } bign1 operator += (const bign1& b) { *this = *this + b; return *this; } void clean()//把0排除,得到真实的len { while (len > 1 && !s[len - 1]) len--; } bign1 operator - (const bign1& b) const { bign1 c; c.len = 0; for (int i = 0, g = 0; i < len; i++) { int x = s[i] - g;//减去借1 if (i < b.len) x -= b.s[i];//上减下 if (x >= 0) g = 0; else { g = 1;//x<0说明需要向前借1 x += 10;//将x变为正 } c.s[c.len++] = x; } c.clean();//x可能为0 return c; } bign1 operator -= (const bign1& b) { *this = *this - b; return *this; } bign1 operator * (const bign1& b) const { bign1 c; c.len = len + b.len;//结果的位数最大为两个因子位数之和 for (int i = 0; i < len; i++) for (int j = 0; j < b.len; j++) c.s[i + j] += s[i] * b.s[j];//对应位置的积的和,累加起来就是结果 for (int i = 0; i < c.len - 1; i++) { c.s[i + 1] += c.s[i] / 10;//进位的值 c.s[i] %= 10;//余数位 } c.clean(); return c; } bign1 operator *= (const bign1& b) { *this = *this * b; return *this; }};struct bign{ int len, s[maxn]; bign()//构造函数 { memset(s, 0, sizeof(s)); len = 1; } bign(bign1& A) { len = A.len; for(int i = 0; i < len; i++) { s[i] = A.s[i]; } } bign operator = (const char * num) { len = strlen(num); for (int i = 0; i < len; i++) s[i] = num[len - i - 1] - '0'; return *this; } bign(const char * num){ *this = num; }//支持初始化操作 bign operator = (int num) { char s[maxn]; sprintf(s, "%d", num);//把num输出到字符串s中 *this = s; return *this; } bign(int num){ *this = num; } string str() const //利用string类把字符串数组转换为字符串,方便用<<,>>输出 { string res = ""; for (int i = 0; i < len; i++) res = (char)(s[i] + '0') + res; if (res == "") res = "0"; return res; } bign operator + (const bign& b) const//定义加法 { bign c; c.len = 0; for (int i = 0, g = 0; g || i < max(len, b.len); i++)//要两个数的位数都计算一便 { int x = g;//g为其余数 if (i < len) x += s[i]; if (i < b.len) x += b.s[i]; c.s[c.len++] = x % 10; g = x / 10; } return c; } bign operator += (const bign& b) { *this = *this + b; return *this; } void clean()//把0排除,得到真实的len { while (len > 1 && !s[len - 1]) len--; } bign operator - (const bign& b) const { bign c; c.len = 0; for (int i = 0, g = 0; i < len; i++) { int x = s[i] - g;//减去借1 if (i < b.len) x -= b.s[i];//上减下 if (x >= 0) g = 0; else { g = 1;//x<0说明需要向前借1 x += 10;//将x变为正 } c.s[c.len++] = x; } c.clean();//x可能为0 return c; } bign operator -= (const bign& b) { *this = *this - b; return *this; } bign operator * (const bign& b) const { bign c; c.len = len + b.len;//结果的位数最大为两个因子位数之和 for (int i = 0; i < len; i++) for (int j = 0; j < b.len; j++) c.s[i + j] += s[i] * b.s[j];//对应位置的积的和,累加起来就是结果 for (int i = 0; i < c.len - 1; i++) { c.s[i + 1] += c.s[i] / 10;//进位的值 c.s[i] %= 10;//余数位 } c.clean(); return c; } bign operator *= (const bign& b) { *this = *this * b; return *this; }};istream& operator >> (istream &in, bign& x)//{ string s; in >> s; x = s.c_str(); return in;}ostream& operator << (ostream &out, const bign& x){ out << x.str(); return out;}bign1 c[110][110];void init2() { c[0][0] = 1; for(int i = 1; i <= 100; i++) { c[i][0] = 1; for(int j = 1; j <= i; j++) { c[i][j] = c[i-1][j-1]+c[i-1][j]; } }}int n;bign ans[110];void init() { ans[0] = 1; ans[1] = 0; ans[2] = 1; bign t = 1; int last = 0; for(int i = 3; i <= n; i++) { bign tmp = 0; for(int j = 1; j <= i; j++) { tmp += ((bign)c[i][j])*ans[i-j]; } for(int j = last; j < i*(i-1)/2; j++) t = t * 2; //if(i==100) cout << t << endl; last = i*(i-1)/2; ans[i] = t - tmp; } cout << ans[n] << endl;}int main(){ freopen("trains.in", "r", stdin); freopen("trains.out", "w", stdout); init2(); cin >> n; init(); return 0;}
Java:
import java.math.BigInteger;import java.util.Scanner;import java.io.*;public class Main { public static void main(String[] args) throws FileNotFoundException { FileInputStream cin = new FileInputStream("trains.in"); FileOutputStream cout = new FileOutputStream("trains.out"); Scanner in = new Scanner(cin); PrintStream out = new PrintStream(cout); BigInteger[][] C = new BigInteger[110][110]; C[0][0] = BigInteger.ONE; for (int i = 1; i <= 100; i++) { C[i][0] = C[i][i] = BigInteger.ONE; for (int j = 1; j < i; j++) { C[i][j] = C[i - 1][j].add(C[i - 1][j - 1]); } } int n = in.nextInt(); in.close( ) ; BigInteger[] ans = new BigInteger[110]; for (int i = 0; i < ans.length; i++) { ans[i] = BigInteger.valueOf(1); } BigInteger two = BigInteger.valueOf(2); for (int i = 3; i <= n; i++) { for (int j = 2; j < i; j++) { if (j == i - 1) ans[i] = ans[i].add(ans[j].multiply(two.pow(j).subtract( BigInteger.ONE))); else ans[i] = ans[i].add(ans[j].multiply(two.pow(j).multiply( C[i - 1][j]))); } } out.println(ans[n]); out.close() ; }}
python:
import sysC = []def init(): for i in range(115): C.append([]) for j in range(115): C[i].append(0) C[0][0] = 1 for i in range( 1 , 110 ): C[i][0] = 1 for j in range( 1 , i+1 ): C[i][j] = C[i-1][j-1] + C[i-1][j] #print( C[4][2] )def work( n ): ans = [] ans.append( 1 ) ans.append( 0 ) ans.append( 1 ) t = 1 last = 0 for i in range( 3 , 105 ): tmp = 0 for j in range( 1 , i+1 ): tmp = tmp + C[i][j] * ans[i-j] for j in range( last , int( i * ( i - 1 ) / 2 ) ): t = t * 2 last = i * ( i - 1 ) // 2 ans.append( t - tmp ) print( ans[n] )sys.stdin = open('trains.in', 'r')sys.stdout = open('trains.out', 'w') init()n = input()work( int( n ) )
0 0
- Gym 100338H High Speed Trains(高精度)
- ACdream 1420 High Speed Trains(容斥原理+高精度)
- ACdream 1420 High Speed Trains【Java大数高精度 + 递推】
- Acdream 1420 High Speed Trains(大数 + 容斥原理)
- 递推 ACdream1420 High Speed Trains
- ACdream 1420 High Speed Trains(容斥原理)
- Bluetooth 3.0+High Speed(HS)
- high-speed LISP interpreter
- 高精度计时器(High Resolution Timer)
- MFC画柱状图之High-speed Charting Control(待续)
- USB之high-speed high-bandwidth endpoint
- High Speed Amplifier Application Notes
- Trains
- GYM 100247 H. Secret Information(贪心)
- GYM 100827 H.Pushups(01背包)
- GYM 100182 H.Robot Challenge(dp)
- GYM 101128 H.Sheldon Numbers(枚举)
- GYM 101102 H.Cinema(水~)
- Java循环和方法
- mogodb连接测试
- swift详解之十六-----------GCD基础部分
- 学习Qt5(1)
- Win32 to .NET API Map
- Gym 100338H High Speed Trains(高精度)
- 【Lua】访问C#中的属性和方法-特殊情况-带有out和ref关键字
- 寄存器概念整理
- [分布式java]基于JavaAPI实现消息方式的系统间通信:UDP/IP+NIO
- java快捷键和注释规范
- 黑马程序员——多线程——多线程概述,实现,控制与安全问题的解决
- list<T>类
- Leetcode #226 Invert Binary Tree
- javascript中的函数Function