【68测试20161117】【数论】【乱搞】【前缀和】

第一题:

  素数密度:给一个区间[L,R],求区间中的素数的个数。L、R<=214748367,L-R<=1000000

解:看到这么大的数据都有点慎得慌。首先,根据筛数法,这么大的数只需要筛sqrt(r)大的素数就可以了。把1~sqrt(r)的素数筛出来,然后用这些素数筛L~R的数。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #define ll long long
 6 #define maxn 1000005
 7 #define N 20005
 8 using namespace std;
 9 int l,r,len,ans,pri[maxn],idx;
10 bool vis[maxn],v[maxn];
11 long long ti;
12 void workk()
13 {
14     for (int i=2;i<=maxn;i++)//注意是maxn,不写i*i<=r是因为最后一次乘的时候可能会超int
15     if (!vis[i]){
16         pri[++idx]=i;
17         for (ll j=(ll)i*(ll)i;j<=maxn;j+=i)
18         if (!vis[j]){
19             vis[j]=true;
20         }
21     }
22 }
23 int main()
24 {
25     freopen("prime.in","r",stdin);
26     freopen("prime.out","w",stdout);
27     scanf("%d%d",&l,&r);
28     workk();
29     for (int i=1;i<=idx;i++)
30     {
31         int x=r/pri[i]*pri[i];//***找到离R最近的那个要筛掉的数
32         while (x>pri[i]&&x>=l)//> not >= 因为pri[i]为质数
33         {
34             v[x-l]=true;x-=pri[i];
35         }
36     }
37     for (int i=0;i<=r-l;i++)
38      if (!v[i]) ans++;
39     printf("%d",ans);
40     return 0;
41 }


第二题:

  从1~n的所有数的各个位的数字之和。即123=1+2+3=6.然后每个1~n的数的和。

解:一看就要找规律。按照位数来数这一位重复了多少1~9(∑=45)和余下的。再把每个位求的答案加起来。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #ifdef WIN32
 6 #define AUTO "%I64d"
 7 #else
 8 #define AUTO "%lld"
 9 #endif
10 #define ll long long
11 #define INF 1e9
12 using namespace std;
13 ll n,f[15],ans;
14 void pre()
15 {
16     f[1]=45;
17     for (int i=2;i<=10;i++)
18       f[i]=f[i-1]*10;
19 }
20 int main()
21 {
22     freopen("count.in","r",stdin);
23     freopen("count.out","w",stdout);
24     pre();
25     scanf(AUTO,&n);
26     ll x=1;
27     int st=0;
28     for (int i=0;i<10;i++){
29         x*=10;
30         if (x>n){
31             st=i;
32             break;
33         }
34     }
35     x/=10;
36     while (st>=0)
37     {
38         ll cur=n/x;//当前位的数字
39         if (st==0) {
40             cur=n%10;
41             for(int i=1;i<=cur;i++) ans+=i;//单独处理个位
42         }
43         else{
44             ans+=cur*f[st];//这一位有多少整的1~9:如123中十位上重复了12次1~9
45             ll aa=cur%10;
46             if (aa>1) {
47                 for (int i=1;i<aa;i++)
48                   ans+=x*i;//除了整的1~9还余了很多个,123十位上还应该有10个1 ,233百位上还有100个1,十位上还有10个1,2
49             }
50             ll bb=n-cur*x;//123百位上还应该有23个1 ,十位上还应该有3+1个2
51             ans+=(bb+1)*aa;
52         }
53         x/=10;
54         st--;
55     }
56     printf(AUTO,ans);
57     return 0;
58 }


第三题:

矩形
文件名:brother.pas/c/cpp
时限:1S
空间:256M
Description
  胜负胸中料已明,又从堂上出奇兵。秋实大哥是一个下棋好手,独孤求败的他觉得下棋已经无法满足他了,他开始研究一种新的玩法。
在一个n×m的棋盘上,放置了k个车,并且他在棋盘上标出了q个矩形,表示矩形内部是战略要地。
秋实大哥要求一个矩形内的每一个格子,都至少能被一辆在矩形内的车攻击到,那么这个矩形就是被完整保护的。
现在秋实大哥想知道每一个矩形是否被完整保护。
Input
  第一行包含四个整数n,m,k,q,表示棋盘的大小,车的数量以及矩形的数量。
  接来下k行,每行包含两个整数x,y,表示有一辆车位于从左往右第x列,从下往上第y行。
  接下来q行,每行包含四个整数x1,y1,x2,y2,表示一个矩形的左下角和右上角坐标。
  1≤n,m≤1e5,1≤k,q≤2e5,1≤x1≤x2≤1e5,1≤y1≤y2≤1e5,1≤x≤1e5,1≤y≤1e5。
Output
  输出q行,对于每一次询问,这个矩形若被完整保护了输出"YES",否则输出"NO"。
Sample input
  4 3 3 3
  1 1
  3 2
  2 3
  2 3 2 3
  2 1 3 3
  1 2 2 3
Sample Output
  YES
  YES
  NO
Limit
  此题无小数据



解:说好的没有小数据。我就没有写暴力。结果.....暴力60。车:象棋中的ju,只能走直线。

  暴力:每一行,每一列的前缀和。只要一个矩阵的所有列或者所有行都有至少一个车。O(q*(n+m))复杂度。

  注意:n为列数,m为行数。。。。。。

60分代码:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<vector>
 6 #define maxn 3005
 7 #define N 100005
 8 using namespace std;
 9 int n,m,k,q,idx;
10 int l[maxn][maxn],h[maxn][maxn];
11 bool mp[maxn][maxn];
12 int main()
13 {
14     freopen("brother.in","r",stdin);
15     freopen("brother.out","w",stdout);
16     scanf("%d%d%d%d",&n,&m,&k,&q);
17     for (int i=1;i<=k;i++)
18     {
19         int x,y;
20         scanf("%d%d",&x,&y);
21         //ju[i].xi=x;ju[i].yi=y;
22         mp[x][y]=true;
23     }
24     for (int i=1;i<=n;i++)//lie
25       for (int j=1;j<=m;j++)//hang
26         {
27             l[i][j]=l[i][j-1];
28             h[i][j]=h[i-1][j];
29             if (mp[i][j]) {
30                 l[i][j]++;h[i][j]++;
31             }
32         }
33     for (int i=1;i<=q;i++)
34     {
35         int xi,yi,xj,yj;
36         scanf("%d%d%d%d",&xi,&yi,&xj,&yj);
37         int ti=min(xi,xj),tj=max(xi,xj),tt=min(yi,yj),tv=max(yi,yj);
38         bool hang=true,lie=true;
39         for (int j=ti;j<=tj;j++)
40           if (l[j][tv]-l[j][tt-1]==0) lie=false;
41         for (int j=tt;j<=tv;j++)
42           if (h[tj][j]-h[ti-1][j]==0) hang=false;
43         if (lie||hang){
44             printf("YES\n");
45             continue;
46         }
47         printf("NO\n");
48     }
49     return 0;
50 }
时间: 2024-10-28 20:56:19

【68测试20161117】【数论】【乱搞】【前缀和】的相关文章

SPOJ - POLYNOM Polynomial(数论乱搞)题解

题意 :给你n个数,问你是否存在一个多项式(最多三次方)满足f(i)= xi. 思路:讲一个神奇的思路: x3 - (x - 1)3 = 3x2 - 3x + 1 x2 - (x - 1)2 = 2x + 1 x - (x - 1) = 1 1 - 1 = 0 看了上面这么多,其实已经可以发现一件事情了:如果相邻常数减一次那么就是0:相邻一次式减一次降为常数,减两次为0:相邻二次式减一次降为一次式,减两次降为常数,减三次.... 由此我们可以知道,如果存在一个多项式(最多三次方)满足f(i)=

【BZOJ-2937】建造酿酒厂 前缀和 + 展环为链 + 乱搞

2937: [Poi2000]建造酿酒厂 Time Limit: 1 Sec  Memory Limit: 128 MBSubmit: 70  Solved: 24[Submit][Status][Discuss] Description Abstinence岛上的居民很喜欢饮用纯酿的啤酒.迄今为止,他们都是从波兰进口啤酒,自己不生产.但今年岛上的一个城市决定建造一个酿酒厂,供给其他城市的啤酒需求. 岛上所有的城市都环绕在海岸线上,相邻两城之间用高速公路连接(也就是说,它们近似分布在一个圆上).

学渣乱搞系列之扩展KMP的那点事

扩展KMP牵涉了一些相对运动的姿势,比较费解!本学渣看了一天的扩展KMP,打算写点东西...本文看后,出现的后果本人一概不负责.毕竟我不是很会表达. 扩展KMP是搞什么灰机的?本学渣所知道的扩展KMP是来解集训篇那道字符串题的.有了犯罪动机,现在就要下手.不要以为扩展KMP就以为与KMP关系暧昧.屁大点事,两个根本不是一个东西.只是有点思想是一致的,就是利用已经匹配的信息避免一些不必要的匹配. 以此提高匹配速度.不过扩展KMP也能干KMP干的事.但是速度没KMP那么快. 扩展KMP要造两个数组,

hdu 5246 乱搞

题意:题目太长直接看链接 链接:点我 乱搞题 显然,一个人要想成功,必须大于等于最强的人的战斗力,所以我们从后往前看 这里直接拿例1解释,首先递减排个序 15,13,10,9,8 作差得2,3,1,1, 此时我们从10出发即可成功 同时也发现,战斗力逐渐递增和直接到某个值其实是等价的 于是我们假设战斗力是从15-13-10-9-8变化的,观察这种变化能否成功即可 由13到15,变化为2,则从13出发剩余战斗力至少得提高2 从10到13,战斗力要提高3,而k为3然后10小于m,即成功 看一下反例2

HDU 4937 Lucky Number 乱搞 + 优化

题意:给你一个数n (1- 1e12),问你有多少种进制使得 这个数用这个进制表示只有 3 . 4 . 5. 6 这4个数 解题思路:这里本来是想要枚举的,发现数太大了,这里利用到了一中很巧妙的优化方法,将 2位 和3位转化成为 一元一次 和一元二次方程,就可以有很大的优化,然后只需要枚举到7000即可 1 // File Name: 1003.cpp 2 // Author: darkdream 3 // Created Time: 2014年08月12日 星期二 12时01分53秒 4 5

【NOIP模拟赛】与非 乱搞

biubiu~~~ 正解是线段树维护真值表,但是我觉得对于这道题来说乱搞就够了....... 我们发现如果我们把每一个数都一开始取反就会发现对于最后结果来说 x=x^1,x nand x=x|x ,x nand x nand x=x|x^1|x,x nand x nand x nand x=x|x^1|x^1|x.....而且我们还发现|0是无效,而且|1之后如有操作择从0开始若无操作则为1,那么我们可以维护我们处理过的x在序列上的前缀和以及他们从一开始进行操作然后每一位都停止一次的前缀答案和,

uva 10780 Again Prime? No Time. 质因子乱搞

求最大的k   使得 m^k 能被n!整除 m^k就是让m的每个质因子个数增加了k倍,只要求得n!的质因子能让m增加多少倍就够了.当然这里要取增加倍数最少的. 木桶装水的量取决于最短的木板. 预处理2-n每个数的质因子情况,由于n有10000,前10000个素数有1000+个,所以维护前缀和不划算. case只有500 所以干脆每次都算一遍. #include<stdio.h> #include<string.h> #include<iostream> #include

【bzoj5108】[CodePlus2017]可做题 拆位+乱搞

题目描述 给出一个长度为 $m$ 的序列 $a$ ,编号为 $a_1\sim a_m$,其中 $n$ 个位置的数已经确定,剩下的位置的数可以任意指定.现在令 $b$ 表示 $a$ 的前缀异或和,求 $\sum\limits_{i=1}^mb_i$ 的最小值. 输入 输入第一行两个非负整数n,m,分别表示原始序列a的长度及剩余元素的个数. 之后m行,每行2个数i,ai,表示一个剩余元素的位置和数值. 1<=N<=10^9,0<=M<=Min(n,10^5),0<=ai<=

[USACO08OCT]牧场散步Pasture Walking (LCA) (乱搞)

题面传送门我太懒了所以吃掉题面 题解 可以发现如果两点不在一条链上的话,那么他们的最短路径一定会经过LCA. 所以可以维护一下每个点到树根的距离,然后大力前缀和乱搞就好了. #include <bits/stdc++.h> const int max_n=1e4+5; int N,M,cnt; int depth[max_n],father[15][max_n],lg2[max_n],first_edge[max_n],dis[max_n]; struct edge { int to,w,ne