1. 程式人生 > >TOJ 1086 Round and Round We Go 大數相乘

TOJ 1086 Round and Round We Go 大數相乘

1086: Round and Round We Go 

時間限制(普通/Java):1000MS/10000MS     記憶體限制:65536KByte
總提交: 254            測試通過:165

描述

A cyclic number is an integer n digits in length which, when multiplied by any integer from 1 to n, yields a"cycle"of the digits of the original number. That is, if you consider the number after the last digit to "wrap around"back to the first digit, the sequence of digits in both numbers will be the same, though they may start at different positions.For example, the number 142857 is cyclic, as illustrated by the following table: 
142857 *1 = 142857 
142857 *2 = 285714 
142857 *3 = 428571 
142857 *4 = 571428 
142857 *5 = 714285 
142857 *6 = 857142

輸入

Write a program which will determine whether or not numbers are cyclic. The input file is a list of integers from 2 to 60 digits in length. (Note that preceding zeros should not be removed, they are considered part of the number and count in determining n. Thus, "01"is a two-digit number, distinct from "1" which is a one-digit number.)

輸出

For each input integer, write a line in the output indicating whether or not it is cyclic.

樣例輸入

142857
142856
142858
01
0588235294117647

樣例輸出

142857 is cyclic
142856 is not cyclic
142858 is not cyclic
01 is not cyclic
0588235294117647 is cyclic

題目來源

大數向量相乘,上半部分程式碼是Karatsuba演算法 的板子,下面是對這題的判斷,迴圈數最多隻要*9,因為*10的話位數肯定會增加就不是迴圈數啦。

#include<iostream>
using namespace std;
#include<vector>
#include<math.h>
vector<int> a,b;
// 向量相加 
vector<int> Add(vector<int> &a,vector<int> &b,int k)
{
    for(int i=0;i<k;i++) b.push_back(0);    //b*10^k
    int asize = a.size();
    int bsize = b.size();
    if(asize<bsize) return Add(b,a,0);  //a比b短   
    int flag,n,diff;
    flag = 0;   //進位 
    diff = asize - bsize; //相差位數 
    for(int i=asize-1;i>=0;i--){    //從最後一位開始加 
        if(i-diff >= 0)n = a[i]+b[i-diff]+flag;
        else n=a[i]+flag;
        flag = n/10;
        a[i] = n%10;

    }
    if(flag > 0){   //處理最高位進位 
        a.push_back(1);
        for(int i=asize;i>=1;i--){
            a[i] = a[i-1];
        }
        a[0] = flag;
    }
    return a;
}
// 向量相減 
vector<int> Sub(vector<int> &a,vector<int> &b)
{
    int asize = a.size();
    int bsize = b.size();
    if(asize<bsize) return Sub(b,a);    //a比b短 
    int flag,n,diff;
    flag = 0;
    diff = asize - bsize;   //相差位數 
    for(int i=asize-1;i>=0;i--){
        if(i-diff >= 0)n = a[i]-b[i-diff]+flag;
        else n=a[i]+flag;
        if(a[i]-b[i-diff] < 0 && i-diff >=0){
            flag = -1;
            a[i] = 10+n;
        }
        else{
            flag = 0;
            a[i] = n;
        }
    }
    int cntzero = 0;    //高位的零的個數 
    for(int i=0;i<a.size();i++){
        if(a[i] == 0) cntzero++;
        else break;
    }
    for(int i=0;i<a.size();i++) //消除高位的零 
        a[i] = a[i+cntzero];
    for(int i=0;i<cntzero;i++)//刪除多餘部分 
        a.pop_back();

    return a;
}

//向量乘法
 vector<int> Multi(vector<int> &a,vector<int> &b)
{
    if(a.size()>b.size()) 
		return Multi(b,a);    //a比b大 
    vector<int> v(a.size() + b.size() +1);  //結果陣列 v 
    int diff = b.size()-a.size();
    for(int i=0;i<a.size();i++)
	{   //迴圈相加 
        for(int j=0;j<b.size();j++)
        v[i+j] += a[a.size()-1-i] * b[b.size()-1-j];
     }  
	for(int i=0;i<v.size();i++)
	{
         if(v[i]<0)
		 {
            int borrow = (abs(v[i]) + 9) /10;
            v[i+1] -= borrow;
            v[i] +=borrow*10;
         }
         else
 		 {
            v[i+1] += v[i] /10;
            v[i] %= 10;
         }  
     }
     while(v.size() > 1&&v.back() == 0) 
	 	v.pop_back();//去除 v 多於部分 
     vector<int> c(v.size());
     for(int i=0;i<v.size();i++)
	 {
        c[i] = v[v.size()-1 - i];   //倒序輸出 
     }
     return c;
 }
// Karatsuba演算法 
vector<int> Karatsuba(vector<int> &a,vector<int> &b)
{
    int asize = a.size();
    int bsize = b.size();
    if(asize <2 || bsize <2) 
		return Multi(a,b); //長度小於2 使用普通乘法 
    if(asize < bsize) 
		return Karatsuba(b,a);    //保證 a長度比b大 
    if(asize == 0 || bsize == 0) 
		return vector<int>();
    int half = asize / 2;   //去一半 
    // a 分成 a1(高位),a0(低位) 
    vector<int> a1(a.begin(),a.end()-half);
    vector<int> a0(a.end()-half,a.end());
    //同理 b 
    vector<int> b1(b.begin(),b.end()-min(half,bsize));
    vector<int> b0(b.end()-min(half,bsize),b.end());

    vector<int> z0 = Karatsuba(a0,b0);
    vector<int> z2 = Karatsuba(a1,b1);
    vector<int> tmpa = Add(a0,a1,0),tmpb = Add(b0,b1,0);
    vector<int> z1 = Karatsuba(tmpa,tmpb);          

    z1 = Sub(z1,z0);
    z1 = Sub(z1,z2);

    vector<int> ret;
    ret.push_back(0);

    ret = Add(ret,z0,0);
    ret = Add(ret,z1,half);
    ret = Add(ret,z2,half*2);

    return ret;
}
int main()
{
    char x[100];
    int i,j,l,p,len,flag;
    while(scanf("%s",x)!=EOF)
	{
		a.clear();
		b.clear();
		flag=0;
		len=strlen(x);
		for(i=0;i<len;i++)
		a.push_back(x[i]-'0');
		for(i=2;i<=len;i++)
		{
			if(i>=10)break;
			b.clear();
			if(i<10)
			b.push_back(i);
			else
			{
				b.push_back(i/10);
				b.push_back(i%10);
			}			
			/*for(j=0;j<b.size();j++)
			printf("%d ",b[j]);
			printf("***\n");*/
			vector<int> v=Karatsuba(a,b);
			int n=v.size();
			/*for(j=0;j<n;j++)
			printf("%d",v[j]);
			printf("\n****\n");*/
			int k=0;
			for(p=0;p<len;p++)
			{
				if((x[p]-'0')==v[0])
				{
					k=0;
					for(j=p,l=0;l<len;j++,l++)
					{
						if((x[j%len]-'0')==v[l])k++;
						else
						{
							k=0;
							break;
						}
					}
					if(k==len)break;
				}
			}
			if(k==len)continue;
			else
			{
				flag=1;
				break;
			}
		}
		if(flag)
		printf("%s is not cyclic\n",x);
		else
		printf("%s is cyclic\n",x);
	}
    
}

奮鬥完之後,發現學姐的程式碼的是這樣的,姜的還是老的辣...

#include<stdio.h>
#include<algorithm>
int main()
{
	char a[62];
	int i,n,s,t;
	while(~scanf("%s",a))
	{
		n=strlen(a);
		for(t=0,i=n-1;i>=0;i--)
		{
			s=(a[i]-'0')*(n+1)+t;
			t=s/10;s=s%10;
			if(s!=9)break;
		}
		printf("%s is%s cyclic\n",a,i+1?" not":"");
	}
}