2008 world final B (Always an Integer)
// 265405 2008-04-18 09:37:54 Accepted 0.205 404 13603 C++ 4119 - Always an integer
/*
问题是判断一个整系数多项式能否总是被整数 divisor 整除
如果 divisor 比较小,我们考虑该整系数多项式 Q(n),看Q(0),Q(1),...,Q(divisor-1)能否被 divisor 整除
每次判断整除性相当于计算多项式值(附带对divisor取模),根据秦九韶算法,复杂度为 O(deg Q),deg Q 为多项式 Q 的次数,故总的复杂度为 O( degQ * divisor )
设给定的多项式为Q(n),如果对于所有的n>0都有 D|Q(n)
显然要满足D|Q(1), 而且Q(n)的差分多项式Q(n+1)-Q(n)也要能被D整除
刚才的思路是计算出 Q'(n) = Q(n+1)-Q(n)
然后在判断 Q'(n)是否满足对与所有n>0 有D|Q'(n)
其实可以不算Q'(n) 直接算是否 D|(Q(n+1)-Q(n))
第一次看是否D整除 Q(1)
第二次看是否D整除 Q(2)-Q(1) 相当与Q'(1)
第三次看是否D整除 Q(3)-2Q(2)+Q(1) 相当与Q''(1)
这时候会发现, 只要计算 Q(1),Q(2),...,Q(degree), 并且判断是否每个值都能被D整除就可以了
因为
第一次查看 Q(1)是否被D整除,如果可以那么
第二次查看 Q(2)-Q(1)是否被D整除,根据上一步的结果,只要满足 Q(2)被D整除就可以有Q(2)-Q(1)被D整除
第三次。。。类似 只要判断是否 Q(3)被D整除
第N次
这些过程中只要出现一次 不能被D整除的 可以马上得出 Not always an integer
*/
#include <stdio.h>
#include <string.h>
// --------------------------------------------------------------------- //
// 类型: Polynomial
// 整系数多项式,附带一个整数的除数
// --------------------------------------------------------------------- //
// 整系数多项式的最高次数
#define Emax 100
bool IsDigit(char c) {
return c>='0' && c<='9';
}
inline int mmax(int a, int b) {
return a>b?a:b;
}
inline int mmin(int a, int b) {
return a<b?a:b;
}
// 类定义: Polynomial
class Polynomial{
public:
//-------------- 公共成员变量 ---------------//
int m_degree; // 整系数多项式的次数
int m_divisor; // 整系数多项式的除数
int m_tab[101]; // 整系数多项式的“系数-幂”对应表
//-------------- 公共成员函数 --------------//
// 初始化为一个零多项式
Polynomial(void){
m_degree = 0;
memset(m_tab, 0, sizeof(m_tab));
}
// 计算系数
int GetCoef(char* str, int index) {
// 省去若干
}
// 计算指数
int GetExp(char* str, int index) {
// 省去若干
}
// 创建一个多项式
void create_polynomial(char* str){
// 省去若干
}
// 判断是否恒被 m_divisor 整除
bool always_divisibility(void){
int i;
for(i=0; i<=m_degree; i++) {
if( evaluate(i) != 0 ) {
return false;
}
}
return true;
}
//-------------- 私有成员函数 ---------------//
// 计算多项式的值(对 m_divisor 求余, 注意可能发生的数据溢出问题)
int evaluate(int n){
long long val = 0;
for(int pow = m_degree; pow >= 0; pow--) {
val = ((val*n)%m_divisor + m_tab[pow])%m_divisor;
}
return (int)val;
}
};
// --------------------- 主函数 ------------------------- //
int main()
{
char str[10000];
char c;
int i;
for(int cases=1; true; cases++){
// input
i = 0;
do{
while( (c=getchar()) != '\n' ) {
if( c==' ' ) continue;
str[i++] = c;
}
str[i] = 0;
}while( strlen(str) == 0 );
if( str[0] == '.' )
break;
// create a polynomial
Polynomial poly;
poly.create_polynomial(str);
// judge and output
printf("Case %d: ", cases);
if( poly.always_divisibility() )
printf("Always an integer\n");
else
printf("Not always an integer\n");
}
return 0;
}
/*
在和钝剑经过激烈的讨论后终于得出了满意的算法,很高兴,希望大家能多多讨论。
在这里感谢钝剑大牛提供我初步代码。
另外这题的字符串解析也是很令人头痛的一步, 在这步因为不够细心WA了N次, 比赛的时候要是遇到这种东西就郁闷了.....
*/
浙公网安备 33010602011771号