`
promiser
  • 浏览: 76321 次
  • 性别: Icon_minigender_1
  • 来自: 广州
文章分类
社区版块
存档分类
最新评论

bzoj1072: [SCOI2007]排列perm

    博客分类:
  • oi
阅读更多

分半搜索,枚举那几个数字分成两半的方案,然后暴力看它们组合Mod d 的余数,并记录,left[i]表示左边的有多少组合mod d = i ,right[i] 也相同,然后用简单数学方法合并

const int N = 15, M = 1010;
int Dat[N], TDat[N], Cnt[2][M], Ans;
int n, Mod;
char S[N];

inline void Solve() ;
inline void NextState(int x, int Pick) ;
inline void Input() {
	int T;
	for(scanf("%d", &T); T--; ) {
		scanf("%s", S), n = strlen(S);
		scanf("%d", &Mod);
		clr(Dat, 0), clr(TDat, 0);
		Rep(i, n) Dat[S[i] - '0']++;
		
		Ans = 0, NextState(0, 0);
		
		printf("%d\n", Ans);
	}
}

inline void NextState(int x, int Pick) {
	if(x >= n >> 1) Solve();
	else {
		For(i, Pick, 9)
			if(TDat[i] < Dat[i]) {
				TDat[i]++;
				NextState(x + 1, i);
				TDat[i]--;
			}
	}
}

inline void Dfs(int Last, int Now, int Type) {
	if(!Last) Cnt[Type][Now % Mod]++;
	else {
		Rep(i, 10)
			if(TDat[i]) {
				TDat[i]--;
				Dfs(Last - 1, Now * 10 + i, Type);
				TDat[i]++;
			}
	}
}
inline void Solve() {
	// Dfs
	clr(Cnt, 0);
	Dfs(n >> 1, 0, 0);
	Rep(i, 10) TDat[i] = Dat[i] - TDat[i];
	Dfs(n - (n >> 1), 0, 1);
	Rep(i, 10) TDat[i] = Dat[i] - TDat[i];
	
	// Count
	int Size = 1;
	Rep(i, n - (n >> 1)) Size *= 10;
	Rep(i, Mod) Ans += Cnt[0][i] * Cnt[1][(Mod - (i * Size) % Mod) % Mod];
}

int main() {
	#ifndef ONLINE_JUDGE
	SETIO("1072");
	#endif
	Input();
	Solve();
	return 0;
}

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics