1. 程式人生 > >【原根】【動態規劃】【bitset】2017四川省賽 K.2017 Revenge

【原根】【動態規劃】【bitset】2017四川省賽 K.2017 Revenge

iostream 我們 eset main pen 乘法 四川 動態 概論

題意:

給你n(不超過200w)個數,和一個數r,問你有多少種方案,使得你取出某個子集,能夠讓它們的乘積 mod 2017等於r。

2017有5這個原根,可以使用離散對數(指標)的思想把乘法轉化成加法,然後就可以用bitset優化dp了。

裸的dp方程是f(i,j)=f(i-1,j)+f(i-1,(j-I(a(i)))%2016),第一維可以滾動。I(i)規定為i的指標,但是我們這裏不像《數論概論》那本書上把I(1)規定為2016,而當成0,比較方便。

#include<cstdio>
#include<bitset>
#include<iostream>
using namespace std;
bitset<2016>f;
int n,a[2000005],r,I[2020];
int main(){
	//freopen("yuangen.in","r",stdin);
	int pw=1;
	for(int i=1;i<2017;++i){
		pw=(pw*5)%2017;
		I[pw]=i;
	}
	I[1]=0;
	while(scanf("%d%d",&n,&r)!=EOF){
		f.reset();
		f.set(I[1]);
		for(int i=1;i<=n;++i){
			scanf("%d",&a[i]);
		}
		for(int i=1;i<=n;++i){
			f^=((f<<I[a[i]])^(f>>(2016-I[a[i]])));
		}
		cout<<f[I[r]]<<endl;
	}
	return 0;
}

【原根】【動態規劃】【bitset】2017四川省賽 K.2017 Revenge