kmjp's blog

競技プログラミング参加記です

101 Hack 45 : D. Polynomial Division

ここら辺まではどうにか。
https://www.hackerrank.com/contests/101hack45/challenges/polynomial-division

問題

整数A,Bと整数列C[i]が与えられる。
以下のクエリを順次処理せよ。

  • C[i]を1箇所値を変更する。
  • 区間[L,R]が与えられる。多項式 \displaystyle P(x) = \sum_{i=L}^R C_i*x^{i-L}が1次式 Q(x) = ax+bでmod pにおいて割り切れるか判定せよ。(p=10^9+7)

解法

P(x)がQ(x)で割り切れるとすると、Q(-b/a)=0よりP(-b/a)も0となるはずである。
あとはBIT等で C_i * (\frac{-B}{A})^iの区間和を取り、mod pにおいて0になるか判定すればよい。

int N,Q;
ll A,B;
ll C[101010];
ll mo=1000000007;
ll V;
ll P[101010];

ll modpow(ll a, ll n = mo-2) {
	ll r=1;
	while(n) r=r*((n%2)?a:1)%mo,a=a*a%mo,n>>=1;
	return r;
}

template<class V, int ME> class BIT {
public:
	V bit[1<<ME];
	V operator()(int e) {V s=0;e++;while(e) s+=bit[e-1],e-=e&-e; return s;}
	void add(int e,V v) { e++; while(e<=1<<ME) bit[e-1]+=v,e+=e&-e;}
};
BIT<ll,20> bt;

void solve() {
	int i,j,k,l,r,x,y; string s;
	
	cin>>N>>A>>B>>Q;
	
	V = (mo-B) * modpow(A) % mo;
	P[0]=1;
	
	FOR(i,N) {
		cin>>C[i];
		bt.add(i+1,C[i]*P[i]%mo);
		P[i+1]=P[i]*V%mo;
	}
	while(Q--) {
		cin>>i>>x>>y;
		if(i==1) {
			bt.add(x+1,(mo-(C[x]*P[x]%mo))%mo);
			C[x]=y;
			bt.add(x+1,C[x]*P[x]%mo);
		}
		else {
			if(B==0) {
				if(C[x]%mo==0) {
					cout<<"Yes"<<endl;
				}
				else {
					cout<<"No"<<endl;
				}
			}
			else {
				ll v=bt(y+1)-bt(x);
				if(v%mo==0) {
					cout<<"Yes"<<endl;
				}
				else {
					cout<<"No"<<endl;
				}
			}
		}
	}
	
	
}

まとめ

多項式系の問題は大体P(x)=0を利用する気がするな。