3653. 她的名字+动态规划

3653. 她的名字

ECNU-3635

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<string>
#include<cmath>
#include<map> 
#include<vector>
#include<unordered_map>
using namespace std;
typedef long long LL;
const int maxn=2004;
const LL mod=1e9+7;
int nums[maxn];
int n;
LL ans[maxn][10][10],C[maxn][maxn],f[maxn][10];//f[pos][y]表示下标pos右边有多少个数字y 
vector<int> pos[10];//各种x数字的出现位置 
int main(){
	//首先计算C
	C[0][0]=1;
	for(int i=1;i<maxn;i++){
		C[i][0]=C[i][i]=1;
		for(int j=1;j<i;j++){
			C[i][j]=(C[i-1][j-1]+C[i-1][j])%mod; 
		}
	} 
	string s;
	cin>>s;
	int index=0;
	for(char ch:s){
		nums[++index]=ch-'0';
	}
	n=index;
	//接着计算f
	for(int i=n-1;i>=1;i--){
		for(int j=0;j<10;j++){
			f[i][j]=f[i+1][j]+(nums[i+1]==j);//i+1位是否是j对应的数字 
		}
		pos[nums[i]].push_back(i); 
	} 
	//dp计算:
	for(int x=0;x<10;x++){
		for(int y=0;y<10;y++){
			if(pos[x].empty()||f[*pos[x].rbegin()][y]==0)
				continue;
			for(int p:pos[x]){//依次遍历出现x数字的位置 
				for(int i=2;i<=n;i++){
					if(p-1<i-2)
						break;
					ans[i][x][y]=(ans[i][x][y]+(C[p-1][i-2]*f[p][y])%mod)%mod;
				} 
			}
		}
	}
	int q;
	cin>>q;
	while(q--){
		int t;
		cin>>t;
		string xy;
		cin>>xy;
		int x,y;
		x=xy[0]-'0';
		y=xy[1]-'0';
//		cout<<x<<" "<<y<<endl;
		if(t>n)
			cout<<0<<endl;
		else{
			cout<<ans[t][x][y]<<endl;
		}
	}
	return 0;
} 
posted @ 2020-10-04 19:16  Garrett_Wale  阅读(132)  评论(0编辑  收藏  举报