【数论Day3】进制问题 题解

数论进入第三天,进制问题是常用提醒,是数论的一个重要知识点,常考!

题面:http://www.cnblogs.com/ljc20020730/p/6935255.html

1.K进制数(Kbased.pas/c/cpp)

首先明确数据范围:

【数据规模和约定】

对于40%的数据,a的长度不超过5。

对于100%的数据,a的长度不超过100000。

对于40%暴力枚举不多说,上代码:

var t,i,k,tt:longint;
    a:qword;
    s:string;
function pow(x,n:qword):qword;
begin
  if n=0 then exit(1);
  pow:=pow(x,n>>1);
  pow:=pow*pow;
  if n mod 2=1 then pow:=(pow*x);
end;
function f(s:string):qword;
var tx,i:longint;
    w:array[0..5]of longint;
    x:qword;
begin
 fillchar(w,sizeof(w),0);
 w[0]:=length(s);
 for i:=1 to length(s) do begin
  if (s[i]<=‘9‘)and(s[i]>=‘0‘) then
  w[i]:=ord(s[i])-ord(‘0‘)
  else w[i]:=ord(s[i])-ord(‘A‘)+10;
 end;
 x:=0;
 tx:=w[0]-1;
 for i:=1 to w[0] do begin
 x:=x+pow(k,tx)*w[i]; dec(tx); end;
 exit(x);
end;
begin
assign(input,‘kbased.in‘);
assign(output,‘kbased.out‘);
reset(input);
rewrite(output);
 readln(t);
 for i:=1 to t do begin
  readln(k);
  readln(s);
  a:=f(s);
  if a mod (k-1)=0 then writeln(‘yes‘)
  else writeln(‘no‘);
 end;
end.

40分非常妥!
但是:对于100%的数据,a的长度不超过100000。
怎么处理?
思考一个问题:每一个k进制数可以表示为什么?

任何一个k进制正整数都可以写成:a0*k0+a1*k1+…+an*kn

这是初赛的内容吧,相信来看题解的人这点心中自然明确。

对于几乎要达到线性的时间复杂度来说,必须要从Kn这里下手!

那么来看一个非常简单的例子:

∵k0=1,∴ k0 mod (k-1) = 1;

∵k1=k-1+1,∴ k1 mod (k-1) = 1;

∵k2 = k*k,∴ k2 mod (k-1) = 1;

……

●所以推出:kn = kn-1*k,kn mod (k-1) = 1

没问题吧?

●任何一个k进制正整数都可以写成:a0*k0+a1*k1+…+an*kn

又因为所有的k?模k-1都是1(?是一个常数)

所以任何一个k进制正整数,模k-1的结果,都等于它各个数位上数字之和模k-1。

任何一个k进制正整数都可以写成:a0*k0+a1*k1+…+an*kn

这是初赛的内容吧,相信来看题解的人这点心中自然明确。

对于几乎要达到线性的时间复杂度来说,必须要从Kn这里下手!

那么来看一个非常简单的例子:

∵k0=1,∴ k0 mod (k-1) = 1;

∵k1=k-1+1,∴ k1 mod (k-1) = 1;

∵k2 = k*k,∴ k2 mod (k-1) = 1;

……

●所以推出:kn = kn-1*k,kn mod (k-1) = 1

没问题吧?

●任何一个k进制正整数都可以写成:a0*k0+a1*k1+…+an*kn

又因为所有的k?模k-1都是1(?是一个常数)

所以任何一个k进制正整数,模k-1的结果,都等于它各个数位上数字之和模k-1。

【程序】

var  w:array[0..100000]of longint;
     t,i,k:longint;
     s:ansistring;
     a:qword;
function f(s:ansistring):qword;
var i:longint;
    ans:qword;
begin
 fillchar(w,sizeof(w),0);
 w[0]:=length(s);
 ans:=0;
 for i:=1 to length(s) do begin
  if (s[i]<=‘9‘)and(s[i]>=‘0‘) then
  w[i]:=ord(s[i])-ord(‘0‘)
  else w[i]:=ord(s[i])-ord(‘A‘)+10;
  inc(ans,w[i]);
 end;
 exit(ans);
end;
begin
assign(input,‘kbased.in‘);
assign(output,‘kbased.out‘);
reset(input);
rewrite(output);
 readln(t);
 for i:=1 to t do begin
  readln(k);
  readln(s);
  fillchar(w,sizeof(w),0);
  a:=f(s);
  if a mod (k-1)=0 then writeln(‘yes‘)
  else writeln(‘no‘);
 end;
 close(input);
 close(output);
end.

2.C and.pas/c/cpp

暴力出奇迹:

20%:N<=1000

另外20%:只有0和1

不解释O(n^2);

非暴力出满分:

【样例分析】

And去运算:0 and 0=0  0 and 1=0  1 and 0=0  1 and 1=1


第1与第2数


第1与第3数


第2与第3数


举例:5 and 23


1 and 2


1 and 1


2 and 1


00101

and  10111

00101


01

and  10


01

and  01


10

and  01


00


01


00


5

另外几个数字!最大数为1 and 1=1。

举例:4个数11 6 10 8

1011

0110

1010

1000

看出来了吧?

用1 2 4得出的数最大!

所以,可以用贪心来解决:为使两数的and最大,故从高位开始(从左向右a[]<=109:31位到0位)枚举,看第1列的1个数有否大于等于2个;若找到,则将其它第1列为0的设为不可用(vis[MAX_N])。继续找后面位也同样处理。

取第i位是否为1:a[j]>>i mod 2=1。同理第i位是否为1: a[j]>>i mod 2=0;

答案为ans:=ans+(1<<i);

var n,i,j,ans,cnt:longint;
    a:array[1..100000]of longint;
    u:array[1..100000]of boolean;
begin
assign(input,‘and.in‘);
assign(output,‘and.out‘);
reset(input);
rewrite(output);
 readln(n);
 fillchar(u,sizeof(u),true);
 for i:=1 to n do read(a[i]);
 for i:=31 downto 0 do begin
  cnt:=0;
  for j:=1 to n do begin
  if (a[j]>>i mod 2=1)and(u[j]) then inc(cnt);
  end;
  if cnt>=2 then begin
    ans:=ans+(1<<i);
    for j:=1 to n do
     if a[j]>>i mod 2=0 then u[j]:=false;
  end;
 end;
 writeln(ans);
 close(input);
 close(output);
end.
时间: 2024-10-11 11:23:06

【数论Day3】进制问题 题解的相关文章

Noip2006 2^k进制数题解

题目描述 Description 设r是个2k进制数,并满足以下条件: (1)r至少是个2位的2k进制数. (2)作为2k进制数,除最后一位外,r的每一位严格小于它右边相邻的那一位. (3)将r转换为2进制数q后,则q的总位数不超过w. 在这里,正整数k(1≤k≤9)和w(k<W≤30000)是事先给定的. 问:满足上述条件的不同的r共有多少个? 我们再从另一角度作些解释:设S是长度为w的01字符串(即字符串S由w个"0"或"1"组成),S对应于上述条件(3)

【数论Day3】进制问题 题目

20170602-1数论_进制 题解:http://www.cnblogs.com/ljc20020730/p/6935240.html 日期 序号 题目名称 输入文件名 输出文件名 时限 内存 算法 难度 081015 1 K进制数 kbased.in kbased.out 1s 256MB 数学分析 1 121028 2 C and.in and.out 1s 128M 数论 2 091110 3 甲型流感 H1N1.IN H1N1.OUT 1s 256MB 快速幂 2 081022 4 数

HDU 4937 Lucky Number (数学,进制转换)

题目 参考自博客:http://blog.csdn.net/a601025382s/article/details/38517783 //string &replace(iterator first0, iterator last0,const_iterator first, const_iterator last); //把[first0,last0)之间的部分替换成[first,last)之间的字符串 /* 题意: 我们将3,4,5,6认为是幸运数字.给定一个十进制数n. 现在可以讲起任意转

题解 P1017 【进制转换】

我赶jio这个题难道是让我们写快写? 不管了,赶紧把咕咕咕了一万年的题解写出来. 这个题就是考察负进制和在mod意义下的除法运算的基础运算. (其实也没多大问题) 首先我们先假设一个原始数据\(num\)和基底\(base(1\leq base\leq20)\) 然后不妨设\(num=a*base+b\)(且$b = num\space mod\space a $ ) 重点来了! 如果\(b<0\),我们就\(b-base,a+1\),很明显这样做是正确的. 为啥呢?因为base是负数.负数减去

P1066 2^k进制数

P1066 2^k进制数 204通过 373提交 题目提供者洛谷OnlineJudge 标签数论(数学相关)高精NOIp提高组2006 难度提高+/省选- 提交该题 讨论 题解 记录 最新讨论 暂时没有讨论 题目描述 设r是个2^k 进制数,并满足以下条件: (1)r至少是个2位的2^k 进制数. (2)作为2^k 进制数,除最后一位外,r的每一位严格小于它右边相邻的那一位. (3)将r转换为2进制数q后,则q的总位数不超过w. 在这里,正整数k(1≤k≤9)和w(k<W< span>≤

bzoj1111 [POI2007]四进制的天平Wag

传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=1111 [题解] 这题号注定单身. 转成四进制考虑 设f[i]表示从第i位往前的min,g[i]表示从第i位往前(第i位借1位)往前的min 那么转移随便做了.. md还要取模,没看这个wa了3发 # include <stdio.h> # include <string.h> # include <iostream> # include <algorithm

- &gt;code vs 1475 m进制转十进制

1475 m进制转十进制 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 白银 Silver 题解 查看运行结果 题目描述 Description 将m进制数n转化成一个十进制数 m<=16 题目保证转换后的十进制数<=100 输入描述 Input Description 共一行 n和m 输出描述 Output Description 共一个数 表示m进制的n化成十进制的数 样例输入 Sample Input 1010 2 样例输出 Sample Output 10 数据范围

hdu 4937 Lucky Number ( 进制转换+枚举 )

题意: 有一个数n,问有多少个进制x(基数)使得n转换为x进制后的数字中只有3.4.5.6四个数. 算法: 对于只有一位数的情况,显然3.4.5.6都应该输出-1. 如果有2位数,假设这2位中高位为a,低位为b,进制为base,则 n = a * base + b,解一元一次方程即可. 如果有3位数,假设这3为从高到低分别为a.b.c,进制为base,则 n = a * base * base + b * base + c,即一元二次方程即可. 如果位数>= 4,可以暴力枚举进制数.base>

-&gt;code vs 1474 十进制转m进制

1474 十进制转m进制 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 白银 Silver 题解 查看运行结果 题目描述 Description 将十进制数n转换成m进制数 m<=16 n<=100 输入描述 Input Description 共一行 n和m 输出描述 Output Description 共一个数 表示n的m进制 样例输入 Sample Input 样例1:10 2 样例2:100 15 样例输出 Sample Output 样例1:1010 样例2:6