Codeword codeforces 666c

/*
不会做
f[i][j] = f[i][j]* 26 + 25^(j-i)*C(i-1)(j-1)
C(i-1)(j-1) 对应j-1最早出现的位置 
1、答案只和字符串长度有关。
2、最多不同的字符串长度只有(k+1)*k/2 = sum , k = sqrt(2*sum) 
代码参考 @ftiasch大神的 
*/

#include<stdio.h>
#include<algorithm>
#include<string.h>
#include<vector>
using namespace std;

typedef long long lld;
const int maxn = 100005;
const int mod = (int)1e9+7;

char ch[maxn];
int fact[maxn];
int a25[maxn];
int inv[maxn];
int q[maxn],t[maxn];
int n , m;

int pow(int x, int n){
	int ret = 1 ;
	while(n){
		if(n&1) ret = (lld)ret*x%mod;
		x = (lld)x*x%mod;
		n >>=1;
	}	
	return ret;
}

void init(){
	fact[0] = a25[0] = inv[0] = 1;
	for(int i = 1 ; i < maxn ; i ++){
		fact[i] = (lld)fact[i-1]*i%mod;
		a25[i] = (lld)a25[i - 1] * 25 %mod;
		inv[i] = pow(fact[i],mod - 2);
	}	
}

vector<int> gao(int x){
	vector<int>ret(maxn , 0);
	ret[x] = 1;
	for(int i = x + 1; i < maxn ; i ++){
		ret[i] =(lld) ret[i - 1]*26%mod+(lld)a25[i-x]*fact[i-1]%mod*inv[x-1]%mod*inv[i-x]%mod;
		ret[i] %= mod;
	}
	return ret ;
}

int main(){
	int i , j , tp , l;
	init();
	//puts("done");
	scanf("%d",&m);
	vector<int> values;
	scanf("%s",ch);
	int ll = strlen(ch);
	values.push_back(ll);
	for(i = 0 ; i < m ; i ++){
		scanf("%d",&t[i]);
		if(t[i] == 1){
			scanf("%s",ch);
			l = strlen(ch);
			q[i] = l;
			values.push_back(l);
		}else{
			scanf("%d",&q[i]);
		}
	}		
	sort(values.begin(),values.end());
	values.erase(unique(values.begin(),values.end()),values.end());
	vector< vector<int> > solve;
    for(i = 0 ; i < values.size(); i ++){
    	solve.push_back(gao(values[i]));
    }
    int cur = ll;
    for(i = 0; i < m ; i ++){
   		if(t[i] == 1){
		   	cur = q[i];
	    }else{
    		int idx = lower_bound(values.begin(),values.end(), cur) - values.begin();
    		printf("%d\n",solve[idx][q[i]]);
    	}
    }
	return 0;
} 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值