Online Judge | Problem Set | Authors | Online Contests | User | ||||||
---|---|---|---|---|---|---|---|---|---|---|
Web Board Home Page F.A.Qs Statistical Charts | Current Contest Past Contests Scheduled Contests Award Contest |
Re:test dataIn Reply To:test data Posted by:yygy at 2023-05-12 23:26:37 // 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: |
All Rights Reserved 2003-2013 Ying Fuchen,Xu Pengcheng,Xie Di
Any problem, Please Contact Administrator