UVALive 4119 Always an integer(差分数列+模拟)
2015-10-02 22:13
441 查看
UVALive - 4119 Always an integer
题意:
输入一个关于n的表达式,求该表达式对于任意整数变量n得到的值是否均为整数。思路:
根据差分数列的性质,令 n = 1 , 2 ,3 ,…,k+1,依次带入表达式计算是不是整数。其中k为表达式的最高次幂,写这个题主要还是锻炼一下自己写模拟题的能力。。
代码:
/* * @author FreeWifi_novicer * language : C++/C */ #include<cstdio> #include<iostream> #include<cstring> #include<cstdlib> #include<cmath> #include<algorithm> #include<string> #include<map> #include<set> #include<vector> #include<queue> using namespace std; #define clr( x , y ) memset(x,y,sizeof(x)) #define cls( x ) memset(x,0,sizeof(x)) #define pr( x ) cout << #x << " = " << x << endl #define pri( x ) cout << #x << " = " << x << " " #define test( t ) int t ; cin >> t ; int kase = 1 ; while( t-- ) #define out( kase ) printf( "Case %d: " , kase++ ) #define mp make_pair #define pii pair<int,int> #define pb push_back typedef long long lint; typedef long long ll; typedef long long LL; string s ; vector<pair<lint , int> >v ; int maxe ; lint d ; void init(){ int k = 0 ; v.clear() ; while( s[k] != '/' ) k++ ; d = abs( atol( s.c_str() + k + 1 ) ); s = s.substr( 0 , k ) ; int len = s.length() ; int begin = ( s[0] == '-' )? 2 : 1 ; if( isdigit( s[begin] ) || s[begin] == 'n' ){ begin -- ; s[begin] = '+' ; } len-- ; maxe = 0 ; for( int i = begin ; i < len ; i++ ){ if( s[i] == '+' || s[i] == '-' ){ i++ ; lint c ; int e ; if( s[i] == 'n' ){ c = ( s[i-1] == '-' )? -1 : 1 ; if( s[i+1] == '^' ){ //n^e e = atoi( s.c_str() + i + 2 ) ; while( i + 2 < len && isdigit( s[i+2] ) ) i++ ; i++ ; } else if( s[i+1] != '^' ){//n e = 1 ; } } else if( isdigit( s[i] ) ){ c = atol( s.c_str() + i ) ; if( s[i-1] == '-' ) c = -c ; while( i + 1 < len && isdigit( s[i+1] ) ) i++ ; if( s[i+1] == 'n' && s[i+2] == '^' ) {//cn^e i ++ ; e = atoi( s.c_str() + i + 2 ) ; while( i + 2 < len && isdigit( s[i+2] ) ) i++ ; i++ ; } else if( s[i+1] == 'n' && s[i+2] != '^' ){//cn i ++ ; e = 1 ; } else if( s[i+1] != 'n' ){//c e = 0 ; } } maxe = max( maxe , e ) ; v.pb( mp( c , e ) ) ; } } } lint fast_pow( lint x , int n ){ lint res = 1 ; while( n ){ if( n & 1 ) res = res * x % d ; n >>= 1 ; x = x * x % d ; } return res ; } lint calc( int n ){ lint sum = 0 ; for( int i = 0 ; i < int( v.size() ) ; i++ ){ lint c = v[i].first ; int e = v[i].second ; if( c ) sum = ( sum + c * fast_pow( n , e ) % d ) % d ; sum = ( sum + d ) % d ; } return sum ; } void work(){ init() ; bool ok = true ; for( int i = 1 ; i <= maxe + 5 ; i++ ){ lint x = calc( i ) ; if( x ){ ok = false ; break ; } } if( ok ) puts( "Always an integer" ) ; else puts( "Not always an integer" ) ; s.clear() ; v.clear() ; } int main(){ int kase = 1 ; while( cin >> s && s != "." ){ out(kase) ; work() ; } return 0; }
补一个求表达式值的模板:
map<char,int>priv ; map<char,double>value ; double calc( double a , double b , char op ){ if( op == '+' ) return a + b ; if( op == '-' ) return a - b ; if( op == '*' ) return a * b ; if( op == '/' ) return a / b ; if( op == '^' ) return exp( log(a) * b ) ; //if( op == '^' ) return fast_pow( a , b ) ; } /*中缀表达式计算,str = "x^2+(12n+11/3+x)-5^n" , val['x']=1 , val['n']=2*/ double calculate( string str , map<char,double> val ){ stack<double>num ; stack<char>oper ; priv['+'] = priv['-'] = 3 ; priv['*'] = priv['/'] = 2 ; priv['^'] = 1 ; priv['('] = 10 ; double x , y ; char last = 0 ; int len = str.length() ; for( int i = 0 ; i < len ; i++ ){ if( isalpha( str[i] ) ) num.push( val[str[i]] ) ; else if( isdigit( str[i] ) ){ num.push( atof( str.c_str() + i ) ) ; while( i + 1 < len && isdigit( str[i+1] ) ) i++ ; if( i + 1 < len && str[i+1] == '.' ){ i++ ; while( i + 1 < len && isdigit( str[i+1] ) ) i++ ; } if( i + 1 < len && isalpha( str[i+1] ) ) oper.push( '*' ) ; } else if( str[i] == '(' ) oper.push( str[i] ) ; else if( str[i] == ')' ){ while( oper.top() != '(' ){ y = num.top() ; num.pop() ; x = num.top() ; num.pop() ; char op = oper.top() ; oper.pop() ; num.push( calc( x , y , op ) ) ; } oper.pop() ; } else if( str[i] == '-' && ( last == 0 || last == '(' ) ){ num.push( 0.0 ) ; oper.push( '-' ) ; } else if( priv[str[i]] > 0 ){ while( !oper.empty() && priv[str[i]] >= priv[oper.top()] ){ y = num.top() ; num.pop() ; x = num.top() ; num.pop() ; char op = oper.top() ; oper.pop() ; num.push( calc( x , y , op ) ) ; } oper.push( str[i] ) ; } else continue ; last = str[i] ; } while( !oper.empty() ){ y = num.top() ; num.pop() ; x = num.top() ; num.pop() ; char op = oper.top() ; oper.pop() ; num.push( calc( x , y , op ) ) ; } return num.top() ; }
相关文章推荐
- 1.m分解阶乘之和
- 2.几种递推数
- 3.欧拉函数
- 4.快速幂模m算法
- 5.扩展欧几里得&&中国剩余定理
- 6.数论_web
- 编程之美2015初赛A
- 数论题集
- 阶与原根学习笔记
- HDU 1299 Diophantus of Alexandria
- Leftmost Digit(HDU 1060)
- Rightmost Digit(HDU 1061)
- ZOJ 2674 Strange Limit 欧拉定理
- LeetCode-Palindrome Number
- 组合数求模总结
- 【数论】组合数求模
- [BZOJ1041][HAOI2008][数学乱搞]圆上的整点
- HDU 5341 Gcd and Lcm
- 【数论学习】奇素数分解为两个数平方和
- 【数论学习】数论分析证明