求Sn=m+mm+mmm+...+mm..mmm(有n个m)的值

文章介绍了两种方法解决给定递推数列求和问题:一是通过for循环逐项累加,二是利用数学归纳法得出等比数列公式,同时提到了数值溢出和精度处理的优化。最后,展示了如何利用System.Numerics库的BigInteger进行大数计算。

题目:求S_{n}=m+mm+mmm+...+mm...mmm 的值 

一、做这个题我们其实可以直接一个for求解:

m,mm,mmm...我们很容易知道它们后一项与前一项的关系就是a_{n}=m+10*a_{n-1}

    public static void Sum(int m,int n)
        {
            long sum = 0L;
            long curAn = 0;
            for (int i = 0; i < n; i++)
            {
                curAn = m+ 10* curAn;// An=m+10*A(n-1)
                sum+= curAn;// 求和
            }
            Console.WriteLine(sum);
        }

二、其实也可以用高中学的数列来做

现已知a_{n}=m+10*a_{n-1},下面我们具体来求解a_{n}

第一步转换:

a_{n}+K=10(a_{n-1}+K)

第二步去括号求解K:

a_{n}+K=10*a_{n-1}+10K

a_{n}=10*a_{n-1}+9K

9K=m

解得K=\frac{m}{9} 

第三步,将K=\frac{m}{9} 带入 a_{n}+K=10(a_{n-1}+K)  式子就可变成:

a_{n}+\frac{m}{9}=10(a_{n-1}+\frac{m}{9})  

第四步,求解a_{n}

\frac{a_{n}+\frac{m}{9}}{(a_{n-1}+\frac{m}{9})}=10 

不难发现数列{{a_{n}+\frac{m}{9}} } 以m+\frac{m}{9} 为首项,q=10为公比的等比数列;

那么b_{n}=a_{n}+\frac{m}{9}=b_{1}*q^{n-1}=(m+\frac{m}{9})*10^{n-1} 从而得到:

a_{n}=(m+\frac{m}{9})*10^{n-1}-\frac{m}{9}   得解!

接下来我们利用数学归纳法求解 S_{n}

①式子:

S_{n}=a_{1}+a_{2}+a_{3}+...+a_{n}

 =(m+\frac{m}{9})*10^{0}-\frac{m}{9}+(m+\frac{m}{9})*10^{1}-\frac{m}{9}+(m+\frac{m}{9})*10^{2}-\frac{m}{9}+(m+\frac{m}{9})*10^{3}-\frac{m}{9}+...+(m+\frac{m}{9})*10^{n}-\frac{m}{9}

=(m+\frac{m}{9})*(10^{0}+10^{1}+10^{2}+10^{3}+...+10^{n-1})-n*\frac{m}{9} 

②式子:

q*S_{n}=q*a_{1}+q*a_{2}+q*a_{3}+...+q*a_{n}

            =q*(m+\frac{m}{9})*(10^{0}+10^{1}+10^{2}+10^{3}+...+10^{n-1})-q*n*\frac{m}{9}

我们知道q=10,于是得到③式子:

10*S_{n}=10*a_{1}+10*a_{2}+10*a_{3}+...+10*a_{n}

               =10*(m+\frac{m}{9})*(10^{0}+10^{1}+10^{2}+10^{3}+...+10^{n})-10*n*\frac{m}{9} 

               =(m+\frac{m}{9})*(10^{1}+10^{2}+10^{3}+10^{4}+...+10^{n-1}+10^{n})-10*n*\frac{m}{9} 

③-①:

9*S_{n}=(m+\frac{m}{9})*(10^{n}-10^{0})-n*m ;

所以:

S_{n}=\frac{1}{9}*(m+\frac{m}{9})*(10^{n}-1)-\frac{n*m}{9}

      =\frac{1}{9}*m*[\frac{10}{9}*(10^{n}-1)-n] 

用代码表示:

    public static void Sum2(int m, int n)
        {
            double result = 10 / (double)81 * (Math.Pow(10, n) - 1) * m - n / (double)9;
            long sum = (long)result;
            Console.WriteLine(sum);
        }

2023.12.13 补充:

sum2方法调整,原因:减少数字n小时的溢出以及精度误差。

       public static void Sum2(int m, int n)
        {
            double result = (Math.Pow(10, n) - 1) / 9 * 10 - n;
            result = result / 9 * m;
            long sum = (long)result;
            Console.WriteLine(sum);
        }

优化:利用 System.Numerics 库的 BigInteger计算

     public static void Sum3(int m, int n)
        {
            BigInteger numerator = BigInteger.Multiply( BigInteger.Divide( BigInteger.Pow(10, n) - 1,9),10)-n;
            numerator= numerator / 9 * m;

            Console.WriteLine(numerator);
        }

当然 利用 System.Numerics 库的 BigInteger计算也可以把Sum方法也修改一下,可以计算更大的n与m,如下:

     public static void Sum(int m, int n)
        {
            BigInteger sum = 0L;
            BigInteger curAn = 0;
            for (int i = 0; i < n; i++)
            {
                curAn = m + 10 * curAn;// An=m+10*A(n-1)
                sum += curAn;// 求和
            }
            Console.WriteLine(sum);
        }

 2023.12.13补充结束

总结:方法二要求数据功底较深,用到高中数学归纳法求解求和公式;方法一只需要每次迭代当前a_{n} ,再求和。

function [ctd,varlabel,names,sensors]=ctd_rd(cnv_file,FMT) %#ok<*STOUT> % CTD_RD Reads the SeaBird ASCII .CNV file format % % Usage: CTD=ctd_rd(cnv_file); % % Input: cnv_file = name of .CNV file (e.g. &#39;cast002.cnv&#39;) % % Output: CTD - a data structure containing the CTD data and header info. % % There are various formats possible for time/location information. % Some of these can be handled with an optional second input parameter: % CTD=ctd_rd(cnv_file,FORMAT) % % where FORMAT = &#39;NMEA&#39; for SEASAVE output with GPS included through deckbox % % * System UpLoad Time = Oct 10 1999 18:20:32 % * NMEA Latitude = 48 36.69 N % * NMEA Longitude = 123 13.07 W % * NMEA UTC (Time) = Oct 10 1999 18:20:32 % % &#39;IR&#39; for an internally recording mode with a hand-typed % header in this form: % % ** Latitude = 49 21.092 N % ** Longitude = 121 49.028 W % ** PST (Time) =Nov 23 2000 07:45 % % will also work with SEASAVE output if no % GPS NMEA string available. % (default mode) % % If no &#39;** Time&#39; line gets it from System Upload Time % % &#39;RP&#39; Ignore any header data but decode System Upload Time for % the year, and the &#39;cast&#39; line (DH command) for time - % good for IR mode when to-yo-ing or otherwise too lazy % to create proper headers. % % &#39;LAB&#39; for a mode with no NMEA or header data (i.e. lab % testing) % % Add more lat,lon and date string handling if your .CNV files are different. % % 4-8-98 Rich Signell (rsignell@usgs.gov) % incorporates ideas from code by Derek Fong & Peter Brickley % 19-9-99 R. pawlowicz (ric@ocgy.ubc.ca) % - added a lot more decoding plus the idea of a data stucture for output % 12-6-00 Changes variable names slightly. % 19-2-02 dms as well as dmm.mm formats % 20-5-11 modified by Rowan Fox (ro1@uvic.ca), adding in model #, temp % sensor SN # & cond sensor SN % 16-5-12 can now read new-format cnv files with xml info if nargin==1 FMT=&#39;IR&#39;; end ctd.name=&#39;ctd&#39;; ctd.station=&#39;&#39;; % Open the .cnv file as read-only text if contains(lower(cnv_file),&#39;.cnv&#39;) cnv_file=[cnv_file &#39;.cnv&#39;]; end fid=fopen(cnv_file,&#39;r&#39;); % Read the header. lat=[]; lon=[]; gtime=NaN(1,6); tzone=&#39;unknown&#39;; % Stop at line that starts with &#39;*END*&#39; str=&#39;*START*&#39;; while (~strncmp(str,&#39;*END*&#39;,5)) str=fgetl(fid); switch FMT case &#39;NMEA&#39; if (strncmp(str,&#39;* NMEA Lat&#39;,10)) lat=get_lat(str); elseif (strncmp(str,&#39;* NMEA Lon&#39;,10)) lon=get_lon(str); elseif (strncmp(str,&#39;* NMEA UTC&#39;,10)) gtime=get_timestamp(str); tzone=&#39;UTC&#39;; end case &#39;IR&#39; if any(strfind(str,&#39;Latitude&#39;)) || any(strfind(str,&#39;Lat&#39;)) lat=get_lat(str); elseif any(strfind(str,&#39;Longitude&#39;)) || any(strfind(str,&#39;Long&#39;)) lon=get_lon(str); % Read the TIME string. This may vary with CTD setup. Will need % ** xxxxxxxxxxTimexxxx = 21 Dec 2005 hh:mm:ss % where timezone may also be in there somewhere. elseif strncmp(str,&#39;**&#39;,2) && any(strfind(str,&#39;Time&#39;)) gtime=get_timestamp(str); tzone=&#39;unknown&#39;; if any(strfind(str,&#39;PST&#39;)) tzone=&#39;PST&#39;; elseif any(strfind(str,&#39;PDT&#39;)) tzone=&#39;PDT&#39;; elseif any(strfind(str,&#39;UTC&#39;)) tzone=&#39;UTC&#39;; elseif any(strfind(str,&#39;EST&#39;)) tzone=&#39;EST&#39;; elseif any(strfind(str,&#39;EDT&#39;)) tzone=&#39;EDT&#39;; end % The default - get a time from the &#39;upload&#39; string (usually the other time % strings are later in the file so they will overwrite this, if they exist). elseif (strncmp(str,&#39;* System UpLoad&#39;,15)) tzone=&#39;unknown&#39;; gtime=get_timestamp(str); end case &#39;LAB&#39; if (strncmp(str,&#39;* System UpLoad&#39;,15)) tzone=&#39;unknown&#39;; gtime=get_timestamp(str); end case &#39;RP&#39; if (strncmp(str,&#39;* System UpLoad&#39;,15)) is=strfind(str,&#39;=&#39;); %EXTRACT THE UPLOAD YEAR FOR CAST START TIME Roger 2003sep04 upyearstr=str(is+9:is+12); end %------------------------------------------------------------------- % READ CAST START TIME, SAMPLE RATE, COMPUTE mtime Roger 2003sep04 % * cast 0 06/23 17:38:06 samples 0 to 1334 sample rate = 1 scan every 0.5 seconds if (strncmp(str,&#39;* cast &#39;,7)) %Find slash indslash=find(str==&#39;/&#39;); indcolon=find(str==&#39;:&#39;); if length(indslash)==1 && length(indcolon)>=2 datstr=[upyearstr &#39; &#39;... str(indslash-2:indslash-1) &#39; &#39; ... str(indslash+1:indslash+2) &#39; &#39; ... str(indcolon(1)-2:indcolon(1)-1) &#39; &#39;... str(indcolon(1)+1:indcolon(2)-1) &#39; &#39;... str(indcolon(2)+1:indcolon(2)+2)]; mtime=datenum(str2double(datstr)); gtime=datevec(mtime); fprintf(&#39;Date from CAST START TIME in timezone of SBE clock\n&#39;); else error(&#39;ERROR: CAST START TIME: str does not have expected form&#39;) end end % otherwise error(&#39;Unrecognized format specifier&#39;); end %----------------------------- % % Read the station name from a comment line % if (strncmpi((str),&#39;** station&#39;,10)) ctd.station=strtrim(str(min(strfind(str,&#39;:&#39;))+2:end)); %----------------------------- % % Read the ctd model from a comment line % elseif (strncmp(str,&#39;* Sea-Bird&#39;,10)) ctd.model=str(strfind(str,&#39;Sea-Bird SBE &#39;)+13:strfind(str,&#39; Data File&#39;)-1); %----------------------------- % % Read the ctd temperature sensor SN from a comment line % elseif (strncmp(str,&#39;* Temperature SN = &#39;,19)) ctd.tempsn=str(strfind(str,&#39;* Temperature SN = &#39;)+19:end); %----------------------------- % % Read the ctd conductivity sensor SN from a comment line % elseif (strncmp(str,&#39;* Conductivity SN = &#39;,20)) ctd.condsn=str(strfind(str,&#39;* Conductivity SN = &#39;)+20:end); %----------------------------- % % Read the depth from a comment line % elseif (strncmpi((str),&#39;** depth&#39;,8)) idelim=strfind(str,&#39;:&#39;); ctd.depth=sscanf(str(idelim+1:end),&#39;%f&#39;); if isempty(ctd.depth), ctd.depth=NaN; end % Units? strrem=str(idelim+1:end);strrem(strrem>=48 & strrem<=57)=&#39; &#39;; %#ok<*NASGU> if any(strfind(str(idelim+1:end),&#39; m&#39;)) % OK elseif any(strfind(str(idelim+1:end),&#39; ft&#39;)) ctd.depth=ctd.depth*0.3048; end %------------------------------ % % Get sampling interval % elseif (strncmp(str,&#39;# interval&#39;,10)) ctd.samp_interval=sscanf(str(strfind(str,&#39;:&#39;)+1:end),&#39;%f&#39;); %------------------------------ % % Get start time % elseif (strncmp(str,&#39;# start_time&#39;,12)) ctd.start_time=str(15:end); ctd.start_mtime=datenum(str(15:end),&#39;mmm dd yyyy HH:MM:SS&#39;); %------------------------------ % % Read the variable names & units into a cell array % elseif (strncmp(str,&#39;# name&#39;,6)) var=sscanf(str(7:10),&#39;%d&#39;,1); var=var+1; ctd.varlabel{var}=str(strfind(str,&#39;=&#39;)+2:min([strfind(str,&#39;:&#39;)-1 ... strfind(str,&#39;/&#39;)-1 strfind(str,&#39;-&#39;)-1])); %------------------------------ % % Read the sensor names into a cell array % elseif (strncmp(str,&#39;# sensor&#39;,8)) sens=sscanf(str(10:11),&#39;%d&#39;,1); sensors{sens+1}=str; %#ok<*AGROW> %------------------------------ % % Read the sensor ranges into a cell array % elseif (strncmp(str,&#39;# span&#39;,6)) sens=sscanf(str(8:9),&#39;%d&#39;,1); ctd.spans{sens+1}=sscanf(str(strfind(str,&#39;=&#39;)+1:end),&#39;%f,%f&#39;); % % pick up bad flag value elseif (strncmp(str,&#39;# bad_flag&#39;,10)) isub=13:length(str); bad_flag=sscanf(str(isub),&#39;%g&#39;,1); end end %============================================== % Done reading header. Now read the data! nvars=var; %number of variables % Read the data into one big matrix data=fscanf(fid,&#39;%f&#39;,[nvars inf]).&#39;; fclose(fid); % Flag bad values with NaN data(data==bad_flag)=NaN; if exist(&#39;sensors&#39;), ctd.sensors=char(sensors); end %#ok<*EXIST> ctd.latitude=lat; ctd.longitude=lon; ctd.gtime=gtime; ctd.mtime=datenum(gtime(1),gtime(2),gtime(3),gtime(4),gtime(5),gtime(6)); ctd.tzone=tzone; if strcmp(FMT,&#39;RP&#39;) ctd.mtimescan=(0:size(data,1)-1)*ctd.samp_interval/86400+mtime; end labeldel=[]; for k=1:length(ctd.varlabel) if diff(ctd.spans{k})~=0 eval([&#39;ctd.&#39; ctd.varlabel{k} &#39;=data(:,k);&#39;]); else labeldel=[labeldel k]; end end ctd.varlabel(labeldel)=[]; ctd.spans(labeldel)=[]; return %--------------------------------------------------- function lon=get_lon(str) % decodes latitude from input string % Get delimiter - &#39;=&#39; or &#39;:&#39; is=strfind(str,&#39;=&#39;); if isempty(is), is=strfind(str,&#39;:&#39;); end isub=is+1:length(str); dm=sscanf(str(isub),&#39;%f&#39;); % E or W if(contains(str(isub),&#39;E&#39;)) sigl=1; else sigl=-1; end % dd.ddd or dd mm.mmm or dd mm ss formats switch (length(dm)) case 1 lon=sigl*dm; case 2 lon=sigl*(dm(1)+dm(2)/60); case 3 lon=sigl*(dm(1)+dm(2)/60+dm(3)/3600); otherwise lon=NaN; disp([&#39;Can&#39;&#39;t scan string ->&#39; str &#39;<- for longitude&#39;]); end return; %--------------------------------------------------- function lat=get_lat(str) % decodes latitude from input string % Get delimiter - &#39;=&#39; or &#39;:&#39; is=strfind(str,&#39;=&#39;); if isempty(is), is=strfind(str,&#39;:&#39;); end isub=is+1:length(str); dm=sscanf(str(isub),&#39;%f&#39;); % N or S if(contains(str(isub),&#39;N&#39;)) sigl=1; else sigl=-1; end % dd.ddd or dd mm.mmm or dd mm ss formats switch (length(dm)) case 1 lat=sigl*dm; case 2 lat=sigl*(dm(1)+dm(2)/60); case 3 lat=sigl*(dm(1)+dm(2)/60+dm(3)/3600); otherwise lat=NaN; disp([&#39;Can&#39;&#39;t scan string ->&#39; str &#39;<- for longitude&#39;]); end return; %-------------------------------------------------- function gtime=get_timestamp(str) % Decodes time string % Time to right of &#39;=&#39; idelim=strfind(str,&#39;=&#39;); if any(idelim) str=str(idelim+1:end); else % try a colon delimiter idelim=strfind(str,&#39;:&#39;); if any(idelim) str=str(idelim(1)+1:end); end end % is there hh:mm:ss in there? is=strfind(str,&#39;:&#39;); if any(is) isub=is(1)-2:length(str); % Date in Dec 21 2005 HH:MM format nbl=find(str(1:is(1)-3)~=&#39; &#39;); datstr=str(min(nbl):max(nbl)); ibl=strfind(datstr,&#39; &#39;); if length(ibl)==2 % Write into 21-Dec-2001 format which matlab can decode datstr=[datstr(ibl(1)+1:ibl(2)-1) &#39;-&#39; datstr(1:ibl(1)-1) &#39;-&#39; datstr(ibl(2)+1:end)]; if ibl(2)-ibl(1)==2 datstr=[&#39;0&#39; datstr]; end gtime=datevec(datstr); % Add hh:mm:ss if length(is)==1 gtime(4:5)=sscanf(str(isub),&#39;%d:%2d&#39;); elseif length(is)==2 gtime(4:6)=sscanf(str(isub),&#39;%d:%2d:%2d&#39;); else disp([&#39;Can&#39;&#39;t scan string ->&#39; str &#39;<- for time of day&#39;]); gtime=[0 0 0 0 0 0]; end else disp([&#39;Can&#39;&#39;t scan string ->&#39; str &#39;<- for day of year&#39;]); gtime=[0 0 0 0 0 0]; end else disp([&#39;Can&#39;&#39;t scan string ->&#39; str &#39;<- for time of day&#39;]); gtime=[0 0 0 0 0 0]; end
11-04
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值