zoukankan      html  css  js  c++  java
  • vijos-1447 开关灯泡-大整数开方算法

    描述

    一个房间里有n盏灯泡,一开始都是熄着的,有1到n个时刻,每个时刻i,我们会将i的倍数的灯泡改变状态(即原本开着的现将它熄灭,原本熄灭的现将它点亮),问最后有多少盏灯泡是亮着的。

    提示

    范围:40%的数据保证,n<=maxlongint
    100%的数据保证,n<=10^200

    **********************************************************************

    1.编个小程序,打表(1-30),可以看出规律         f(n)=sqrt(n)的下界。

    2.思考如何求大整数的根号:两种思路:迭代法,例如二分法、牛顿迭代等;

    打点法:精确计算,一步到位。笔算开平方法,我二姐教过我。真是太好了。

    我只想简单说个大概:

    i。从后往前,隔两位点一个小数点

    ii。从前往后,试商,做差,落下来

    3.打点法肯定速度非常快O(200*100)的复杂度:根最大是100位,每求一位最多200位的操作。这个过程需要用到大数乘法、减法、移位。

    4.最后一点,在编大数运算时最好按照位数固定进行运算,这样虽然牺牲了一点效率,但可读性好、易于实现。

    5.要背下来大数运算,不要只会抄scl,唯有如此,方能随用随写,剑心合一。

    #include<iostream>
    #include<string.h>
    #include<stdio.h>
    using namespace std;
    #define size 205
    int n[205], ni;
    int ans[205];
    int now[205];
    int two[205];
    int mu[205];
    void getTwo(){//two=(ans*2)<<1;
    	memset(two, 0, sizeof(two));
    	int i;
    	for (i = 0; i < size; i++){
    		two[i] += (ans[i] << 1);
    		two[i + 1] = two[i] / 10;
    		two[i] %= 10;
    	}
    	for (i = size - 2; i >= 0; i--)
    		two[i + 1] = two[i];
    }
    void getNow(){
    	int i;
    	for (i = size - 3; i >= 0; i--){
    		now[i + 2] = now[i];
    	}
    	now[1] = n[ni--];
    	now[0] = n[ni--];
    }
    void mul(int k){//mu=two_k*k
    	memset(mu, 0, sizeof(mu));
    	int i;
    	for (i = 0; i < size; i++){
    		mu[i] += two[i] * k;
    		mu[i + 1] = mu[i] / 10;
    		mu[i] %= 10;
    	}
    }
    int cmp(){//now-mu
    	int i;
    	for (i = size - 1; i >= 0; i--)
    	if (now[i] != mu[i])
    		return now[i] - mu[i];
    	return 0;
    }
    void sub(){//now-mu
    	int i;
    	for (i = 0; i < size - 1; i++){
    		now[i] -= mu[i];
    		if (now[i] < 0){
    			now[i + 1]--;
    			now[i] += 10;
    		}
    	}
    }
    void getAns(){
    	int i;
    	for (i = size - 2; i >= 0; i--){
    		ans[i + 1] = ans[i];
    	}
    	for (i = 9; i >= 0; i--){
    		two[0] = i;
    		mul(i);
    		if (cmp() >= 0){
    			ans[0] = i;
    			sub();
    			return;
    		}
    	}
    }
    void go(){
    	while (ni >= 0){
    		getTwo();
    		getNow();
    		getAns();
    	}
    }
    int main(){
    	freopen("in.txt", "r", stdin);
    	char a[205];
    	int i;
    	for (i = 0; a[i]; i++);
    	ni = i;
    	memset(n, 0, sizeof(n));
    	for (i = 0; i < ni; i++)
    		n[i] = a[ni - 1 - i] - '0';
    	if ((ni & 1) == 0)ni--;
    	memset(ans, 0, sizeof(ans));
    	memset(now, 0, sizeof(now));
    	go();
    	for (i = size - 1; ans[i] == 0; i--);
    	for (; i >= 0; i--)cout << ans[i];
    	return 0;
    }
    


  • 相关阅读:
    十度好友问题
    TCP传输连接建立与释放详解
    Android多点触控技术实战,自由地对图片进行缩放和移动
    如何判断一个变量是数组Array类型
    HDU 4725 The Shortest Path in Nya Graph-【SPFA最短路】
    解决外贸电商难题,PayPal中国外贸电商大会圆满礼成
    动物-蛇:家蛇
    动物-蛇:水蛇
    动物-鱼:河蟹
    动物-鱼:河虾
  • 原文地址:https://www.cnblogs.com/weiyinfu/p/5013891.html
Copyright © 2011-2022 走看看