Online JudgeProblem SetAuthorsOnline ContestsUser
Web Board
Home Page
F.A.Qs
Statistical Charts
Problems
Submit Problem
Online Status
Prob.ID:
Register
Update your info
Authors ranklist
Current Contest
Past Contests
Scheduled Contests
Award Contest
User ID:
Password:
  Register

写了12K的代码,1A了,高兴。

Posted by yygy at 2023-05-14 21:29:43 on Problem 1863
In Reply To:Re:test data Posted by:yygy at 2023-05-13 13:00:27
> // MyFirstApp.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
> //
> 
> #include <iostream>
> #include <vector>
> #include <stdio.h>
> #include <math.h>
> #include <algorithm>
> 
> using namespace std;
> 
> typedef __int64 lld;
> 
> const int MAXN = 20010;
> 
> struct BigNum
> {
> 	int dig[512];//题目说最多200位,平方之后最多400位
> 	int len;
> 	BigNum() {}
> 	BigNum(int arr[], int size) 
> 	{
> 		clr();
> 		len = size;
> 		for (int i = 0; i < len; i++)
> 		{
> 			dig[len - i - 1] = arr[i];
> 		}
> 	}
> 	void clr()
> 	{
> 		memset(dig, 0, sizeof(int) * 512);
> 		len = 1;
> 	}
> 
> 	void operator --()
> 	{
> 		dig[0]--;
> 		int bit=0;
> 		while (dig[bit] < 0)
> 		{
> 			dig[bit] += 10;
> 			dig[bit + 1] --;
> 			bit++;
> 		}
> 
> 		while (len > 1 && dig[len - 1] == 0)
> 		{
> 			len--;
> 		}
> 	}
> 
> 	int Compare(const BigNum& other) const
> 	{
> 		if (len < other.len)
> 		{
> 			return -1;
> 		}
> 
> 		if (len>other.len)
> 		{
> 			return 1;
> 		}
> 
> 		for (int i = len-1; i>=0; i--)
> 		{
> 			if (dig[i] != other.dig[i])
> 			{
> 				return dig[i] - other.dig[i];
> 			}
> 		}
> 
> 		return 0;
> 	}
> 
> 	void operator ++()
> 	{
> 		dig[0]++;
> 		int bit = 0;
> 		while (dig[bit] > 9)
> 		{
> 			dig[bit] -= 10;
> 			dig[bit + 1] ++;
> 			bit++;
> 		}
> 
> 		if (dig[len])
> 		{
> 			len++;
> 		}
> 	}
> 
> 	void Add(int x)
> 	{
> 		dig[0]+=x;
> 		for(int i=0;i<len;i++)
> 		{
> 			if(dig[i]>=10)
> 			{
> 				dig[i+1]+=dig[i]/10;
> 				dig[i]%=10;
> 			}
> 		}
> 
> 		while(dig[len])
> 		{
> 			dig[len+1]+=dig[len]/10;
> 			dig[len]%=10;
> 			len++;
> 		}
> 	}
> 
> 	void print()
> 	{
> 		for(int i=len-1;i>=0;i--)
> 		{
> 			printf("%d", dig[i]);
> 		}
> 	}
> };
> 
> bool IsSuffix(const BigNum& num, int* pat, int size)
> {
> 	if (size > num.len)
> 	{
> 		return false;
> 	}
> 
> 	for (int i = 0; i < size; i++)
> 	{
> 		if (num.dig[i] != pat[size - i - 1])
> 		{
> 			return false;
> 		}
> 	}
> 
> 	return true;
> }
> 
> bool Match(int* pat, int patlen, const BigNum& tmp, int last)
> {
> 	int i = 0;
> 	for (i = 0; i < tmp.len && last + i < patlen; i++)
> 	{
> 		//BigNum从高位比起
> 		if (tmp.dig[tmp.len-i-1] != pat[last + i])
> 		{
> 			return false;
> 		}
> 	}
> 
> 	return i == tmp.len || last + i == patlen;
> }
> 
> void MakeStr(int *pat, int len, std::vector<int>& a)
> {
> 	for(int i=0;i<len;i++)
> 	{
> 		a.push_back(pat[i]);
> 	}
> }
> 
> bool Match(std::vector<int>::iterator beginA, std::vector<int>::iterator endA,
> 	const std::vector<int>& strA)
> {
> 	int i=0;
> 	while(beginA<endA)
> 	{
> 		if(*beginA!=strA[i])
> 		{
> 			return false;
> 		}
> 		i++;
> 		beginA++;
> 	}
> 
> 	return true;
> }
> 
> void Concat(const std::vector<int>& strb, const std::vector<int>& stra,
> 	int pos,
> 	std::vector<int>& num)
> {
> 	int rearSize=stra.size()-(strb.size()-pos);
> 	num=strb;
> 	num.reserve(rearSize+strb.size());
> 	
> 	for(int i=stra.size()-rearSize;i<stra.size();i++)
> 	{
> 		num.push_back(stra[i]);
> 	}
> }
> 
> void FindSeperateTwoSegments(int patlen, int* pat, BigNum& ans, int& offset)
> {
> 	//枚举中间断开位置
> 	for(int i=0;i+1<patlen;i++)
> 	{
> 		std::vector<int> stra, strb;
> 		//两个串保存起来
> 		MakeStr(pat, i+1, stra);
> 		MakeStr(pat+i+1, patlen-i-1, strb);
> 
> 		//寻找一个前面的前缀等于后面的后缀的位置,然后把这两个串叠起来
> 		//枚举后面串对齐第一个串的首位置
> 		for(int pos=0;pos<=strb.size();pos++)
> 		{
> 			if(strb.size()-pos>stra.size())
> 			{
> 				//后面的串太短,覆盖不了前面串的后缀
> 				continue;
> 			}
> 
> 			if(Match(strb.begin()+pos, strb.end(), stra))
> 			{
> 				std::vector<int> num;
> 				Concat(strb, stra, pos, num);
> 				BigNum pre=BigNum(num.data(), num.size());
> 				if (IsSuffix(pre, pat, i + 1))
> 				{
> 					BigNum tmp = pre;
> 					++tmp;
> 					int last=i+1;
> 					
> 					if (Match(pat, patlen, tmp, last))
> 					{
> 						int newOffset = 1 + pre.len - (i + 1);
> 						int diff=pre.Compare(ans);
> 						if(diff<0)
> 						{
> 							ans=pre;
> 							offset=newOffset;
> 						}
> 						else if(diff==0 && newOffset<offset)
> 						{
> 							offset=newOffset;
> 						}
> 					}
> 					
> 				}
> 			}
> 		}
> 	}
> }
> 
> void FindSeperateSeveralSegments(int patlen, int* pat, BigNum& ans, int& offset)
> {
> 	//把pat分解成前后两部分,后面一部分是由n,n+1,n+2...堆起来的,那么后面的开头数字长度不能小于第一部分
> 	for (int i = 0; patlen - (i + 1) >= i + 1; i++)
> 	{
> 		if (pat[i + 1] == 0)
> 		{
> 			//首位数字必须非0
> 			continue;
> 		}
> 		//枚举后面数字[i+1,j]区间为第一个数字
> 		//j-i>=i+1
> 		for (int j = i + i + 1; j < patlen; j++)
> 		{
> 			printf("i=%d j=%d\n",i,j);
> 			BigNum head = BigNum(pat + i + 1, j - i);
> 			BigNum pre = head;
> 			--pre;
> 			printf("pre="); pre.print();
> 			cout<<endl;
> 
> 			//判断前面部分是否为head-1的后缀
> 			if (!IsSuffix(pre, pat, i + 1))
> 			{
> 				continue;
> 			}
> 
> 			printf("suffix success\n");
> 
> 			int last = i+1;
> 			BigNum tmp = head;
> 			//tmp一直++,把last后面的数字依依匹配,看看能不能配完
> 			while (last < patlen)
> 			{
> 				if (!Match(pat, patlen, tmp, last))
> 				{
> 					break;
> 				}
> 
> 				last += tmp.len;
> 				++tmp;
> 			}
> 
> 			printf("last=%d patlen=%d\n", last, patlen);
> 
> 			if (last >= patlen)//匹配成功
> 			{
> 
> 				int newOffset = 1 + pre.len - (i + 1);
> 				int diff=pre.Compare(ans);
> 
> 				printf("one solution = ");
> 				pre.print();
> 				
> 				printf(", offset=%d\n", newOffset);
> 				//记录一下现在的答案
> 				if (diff<0)
> 				{
> 					ans = pre;
> 					offset = newOffset;
> 				}
> 				else if(diff==0 && newOffset<offset)
> 				{
> 					offset=newOffset;
> 				}
> 			}
> 		}
> 	}
> }
> 
> BigNum Add(const BigNum& a, const BigNum& b)
> {
> 	BigNum c;
> 	c.clr();
> 	c.len=std::max(a.len, b.len);
> 
> 	for(int i=0;i<c.len;i++)
> 	{
> 		c.dig[i]=a.dig[i]+b.dig[i];
> 	}
> 
> 	for(int i=0;i<c.len;i++)
> 	{
> 		if(c.dig[i]>=10)
> 		{
> 			c.dig[i+1]+=c.dig[i]/10;
> 			c.dig[i]%=10;
> 		}
> 	}
> 
> 	if(c.dig[c.len])
> 	{
> 		c.len++;
> 	}
> 
> 	return c;
> }
> 
> void MulTen(BigNum& num)
> {
> 	for(int i=num.len;i>0;i--)
> 	{
> 		num.dig[i]=num.dig[i-1];
> 	}
> 	num.dig[0]=0;
> 	num.len++;
> }
> 
> int BitCount(int n)
> {
> 	if(n==0)
> 	{
> 		return 1;
> 	}
> 
> 	int len=0;
> 	while(n)
> 	{
> 		len++;
> 		n/=10;
> 	}
> 
> 	return len;
> }
> 
> BigNum Mul(const BigNum& a, int b)
> {
> 	BigNum c;
> 	c.clr();
> 	if(b==0)
> 	{
> 		return c;
> 	}
> 	c.len=a.len+BitCount(b);
> 	for(int i=0;i<a.len;i++)
> 	{
> 		c.dig[i]=a.dig[i]*b;
> 	}
> 
> 	for(int i=0;i<c.len;i++)
> 	{
> 		if(c.dig[i]>=10)
> 		{
> 			c.dig[i+1]+=c.dig[i]/10;
> 			c.dig[i]%=10;
> 		}
> 	}
> 
> 	while(c.len>1&& c.dig[c.len-1]==0)
> 	{
> 		c.len--;
> 	}
> 
> 	return c;
> }
> 
> BigNum Minus(const BigNum& a,const BigNum& b)
> {
> 	BigNum c;
> 	c.clr();
> 	c.len=a.len;
> 	for(int i=0;i<a.len;i++)
> 	{
> 		c.dig[i]=a.dig[i]-b.dig[i];
> 	}
> 
> 	for(int i=0;i<a.len;i++)
> 	{
> 		if(c.dig[i]<0)
> 		{
> 			c.dig[i]+=10;
> 			c.dig[i+1]--;
> 		}
> 	}
> 
> 	while(c.len>1&&c.dig[c.len-1]==0)
> 	{
> 		c.len--;
> 	}
> 
> 	return c;
> }
> 
> void CalcIndex(const BigNum& num, int offset, BigNum& pos)
> {
> 	pos.clr();
> 	BigNum nine;
> 	BigNum one;
> 	nine.clr();
> 	nine.dig[0]=9;
> 	one.clr();
> 	one.dig[0]=1;
> 	//先计算长度比num短的数字长度总和
> 	for(int bitLen=1;bitLen<num.len;bitLen++)
> 	{
> 		//长度为bitLen的有nine个,每个长度为bitLen
> 		BigNum length=Mul(nine,bitLen);
> 		printf("bitLen=%d\n", bitLen);
> 		printf("nine=");
> 		nine.print();
> 		std::cout<<endl;
> 		printf("length=");
> 		length.print();
> 		std::cout<<endl;
> 		pos=Add(pos, length);
> 		printf("tempPos=");
> 		pos.print();
> 		std::cout<<endl;
> 		MulTen(nine);
> 		MulTen(one);
> 	}
> 
> 	printf("small length = ");
> 	pos.print();
> 	std::cout<<std::endl;
> 
> 	//统计长度为num.len的个数,以及长度
> 	BigNum equalLengthNum=Minus(num, one);
> 
> 	BigNum otherLength=Mul(equalLengthNum, num.len);
> 	pos=Add(pos, otherLength);
> 
> 	pos.Add(offset);
> }
> 
> int main()
> {
> 	char str[512];
> 	int pat[512];
> 	int patlen = 0;
> 	while (cin.getline(str, 1024))
> 	{
> 		patlen = strlen(str);
> 		for (int i = 0; i < patlen; i++)
> 		{
> 			pat[i] = str[i] - '0';
> 		}
> 
> 		//一个初始解,也就是仅由于段组成的
> 		BigNum ans = BigNum(pat, patlen);
> 		int offset = 1;
> 
> 		if (ans.dig[ans.len - 1] == 0)
> 		{
> 			//最高位为0,需要添加一位,比如0,是10后面来的,01应该是101后面来的
> 			offset++;
> 			ans.dig[ans.len] = 1;
> 			ans.len++;
> 		}
> 
> 		//假设由若干个数字拼成,寻找答案
> 		FindSeperateSeveralSegments(patlen, pat, ans, offset);
> 
> 		//假设只由两个数字拼成,寻找答案
> 		FindSeperateTwoSegments(patlen, pat, ans, offset);
> 
> 		printf("ans=");
> 		ans.print();
> 		std::cout<<std::endl;
> 		printf("offset=%d\n", offset);
> 
> 		BigNum pos;
> 		CalcIndex(ans, offset, pos);
> 
> 		pos.print();
> 		cout<<endl;
> 	}
> 	return 0;
> }
> 
> /*
> http://poj.org/problem?id=1863
> Subnumber
> 要考虑前导0,一堆0的情况
> 
> 1
> ans=1
> offset=1
> 2
> ans=2
> offset=1
> 3
> ans=3
> offset=1
> 101
> ans=10
> offset=1
> 1234
> ans=1
> offset=1
> 234
> ans=2
> offset=1
> 11
> ans=11
> offset=1
> 12
> ans=1
> offset=1
> 13
> ans=13
> offset=1
> 41
> ans=41
> offset=1
> 10111
> ans=110
> offset=2
> 011
> ans=10
> offset=2
> 121
> ans=121
> offset=1
> 123412351236123712381239
> 
> 121314
> 
> 1234123
> 
> 23412
> 3412
> 
> */

Followed by:

Post your reply here:
User ID:
Password:
Title:

Content:

Home Page   Go Back  To top


All Rights Reserved 2003-2013 Ying Fuchen,Xu Pengcheng,Xie Di
Any problem, Please Contact Administrator