把博客园图标替换成自己的图标
把博客园图标替换成自己的图标end

【k进制 计数(?)】 Tavan 6.23测试COCI


样例:

9 2 3 7
po#olje#i
sol
znu
posoljeni



4 1 2 2 
#rak
zm
zrak

之前的做法,由于 2 6 500 26^{500} 26500太大 所以 p [ ] p[] p[]会爆
数据比较小 有90分

#include<cstdio>
#include<vector>
#include<cstring>
#include<iostream>
#include<string>
#include<queue>
#include<algorithm>
using namespace std;
#define MAXN 505
#define LL long long
char s[MAXN],mb[MAXN][30];
int n,m,k,x,num;
LL p[MAXN];
int main()
{
	//freopen("tavan.in","r",stdin);
	//freopen("tavan.out","w",stdout);
	scanf("%d %d %d %d",&n,&m,&k,&x);
    scanf("%s",s+1);
    int cnt=0,sum=1;
	for(int i=1;i<=m;i++)
	{
		scanf("%s",mb[i]+1);
		sort(mb[i]+1,mb[i]+k+1);
		//printf("%s\n",mb[i]+1);
	}
	p[1]=k;
	for(int i=2;i<=m;i++)
		p[i]=k*p[i-1];
	//for(int i=1;i<=m;i++)
	//	printf("%d  ",p[i]);
	for(int i=1;i<=n;i++)
		if(s[i]=='#')
		{
			++num;
			if(num==m)
			{
				s[i]=mb[m][x];
				break;
			}
			else
			{
				int tmp=x/p[m-num];
				if(x%p[m-num]) tmp++;
				//printf("%d\n",tmp);
				s[i]=mb[num][tmp];
				x=x-(tmp-1)*p[m-num];
				/*int tmp=x/k;
				x=x-tmp*k;
				if()
				if(x%k) tmp++;
				s[i]=mb[num][tmp];*/
			}
		}
	puts(s+1);
    return 0;
}

那么就反其道而行之
从最后一位倒着搞回来
有点像k进制(实际上就是k进制吧
也要注意细节
尤其是刚好整除时的情况
代码中的注释很详细了 (注释之述备矣

//正难则反 倒过来统计 
#include<cstdio>
#include<vector>
#include<cstring>
#include<iostream>
#include<string>
#include<queue>
#include<algorithm>
using namespace std;
#define MAXN 505
#define LL long long
char s[MAXN],mb[MAXN][30];
int n,m,k,x,num;
LL p[MAXN];
int main()
{
	//freopen("tavan.in","r",stdin);
	//freopen("tavan.out","w",stdout);
	scanf("%d %d %d %d",&n,&m,&k,&x);
    scanf("%s",s+1);
    int cnt=0,sum=1;
	for(int i=1;i<=m;i++)
	{
		scanf("%s",mb[i]+1);
		sort(mb[i]+1,mb[i]+k+1);
	}
	for(int i=n;i>=1;i--)
	{
		if(s[i]=='#')
		{
			int tmp=x%k;
			if(tmp==0) tmp=k;
			//找规律 周期问题 最后一位取第几个是取决于x%k的
			s[i]=mb[m][tmp];
			m--;
			//x/=k 是把当前已经决定了的这一位抛开 单看剩下的位数 字典序应该排在哪里(画个图大概体会一下 
			if(x%k==0) x/=k; 
			//如果能刚好整除 就恰好是那一组的最后一个
			else x/=k,x++;
			//如果不能整除,除法是下取整的,就跑到了上一组去,所以要加回来
			//整除的商是上一组的字典序 而余数就是在这一位取的值 就是比上一位多多少 这肯定是要算到后一组去的
			//这里的组数指的是除去当前这一位 进行排列的结果 可以看作每一组有k个 详细见下图 
		}
	}
	puts(s+1);
    return 0;
}


然后我最前面考场上的90分做法 看到有个大佬似乎有点像
但没有怎么看懂

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<iostream>
using namespace std;
int len,n,psi,rnk,nsur;
string wrd;
long long powp[505];
char sur[505];
int main(){
	freopen("tavan.in","r",stdin);
	freopen("tavan.out","w",stdout);
	scanf("%d%d%d%d",&len,&n,&psi,&rnk);
	powp[0]=1;
	for(int i=1;i<=500;i++){
		powp[i]=powp[i-1]*psi;
		if(powp[i]>rnk) powp[i]=1000000005;
	}
	cin>>wrd;
	for(int i=1;i<=n;i++){
		string abl;
		cin>>abl;
		sort(abl.begin(),abl.end());
		int f=(rnk-1)/powp[n-i];
		rnk-=f*powp[n-i];
		sur[++nsur]=abl[f];
	}
	for(int i=0,j=1;i<len;i++){
		if(wrd[i]=='#') printf("%c",sur[j++]);
		else printf("%c",wrd[i]);
	}
	printf("\n");
	return 0;
}

但现下也还未决心实践,正在研究而且推敲
玄学之事,难言之矣,这也只得姑且置之弗论了

posted @ 2019-06-24 11:01  Starlight_Glimmer  阅读(10)  评论(0编辑  收藏  举报  来源
浏览器标题切换
浏览器标题切换end