2017-10-07清北模拟赛

 

1 //电脑蓝屏,三个题60分暴力全部丢失。。
事故。

 

noip提高组模拟赛

 

1.计数

(count.cpp/c/pas)

时间限制:1s

内存限制:256MB

【问题描述】

    给出m个数a[1],a[2],…,a[m]

    求1~n中有多少数不是a[1],a[2],…,a[m]的倍数。

【输入】

输入文件名为count.in。

第一行,包含两个整数:n,m

第二行,包含m个数,表示a[1],a[2],…,a[m]

【输出】

输出文件名为count.out。

输出一行,包含1个整数,表示答案

【输入输出样例】

count.in

count.out

10 2

2 3

3

【数据说明】

对于60%的数据,1<=n<=106

对于另外20%的数据,m=2

对于100%的数据,1<=n<=109,0<=m<=20,1<=a[i]<=109

 

 1 /*
 2 暴力做法:m*n    枚举ai,数组记录每个在n内的ai的倍数是否出现过,统计ans 
 3 正解:容斥原理,对于选取的ai的个数,奇数ans减去贡献,偶数加上贡献,累乗ai注意取gcd 
 4 */
 5 #include <algorithm>
 6 #include <cstdio>
 7 
 8 #define LL long long
 9 inline void read(LL &x)
10 {
11     x=0; register char ch=getchar();
12     for(; ch>'9'||ch<'0'; ) ch=getchar();
13     for(; ch>='0'&&ch<='9'; ch=getchar()) x=x*10+ch-'0';
14 }
15 #define GCD(a,b) (std::__gcd(a,b))
16 const int N(26);
17 LL n,m,a[N],ans;
18 
19 void DFS(int op,int cnt,LL sum)
20 {
21     if(sum>n) return ;
22     if(cnt==m+1) { ans+=n/sum*op; return ; }
23     DFS(op,cnt+1,sum);
24     DFS(-op,cnt+1,sum/GCD(sum,a[cnt])*a[cnt]);
25 }
26 
27 int Presist()
28 {
29     read(n);    read(m);
30     for(int i=1; i<=m; ++i) read(a[i]);
31     DFS(1,1,1);    printf("%lld\n",ans);
32     return 0;
33 }
34 
35 int Aptal=Presist();
36 int main(int argc,char**argv){;} 
AC

 

 

 

 

2.第k大区间

(kth.cpp/c/pas)

时间限制:1s

内存限制:256MB

【问题描述】

定义一个长度为奇数的区间的值为其所包含的的元素的中位数。

现给出n个数,求将所有长度为奇数的区间的值排序后,第K大的值为多少。

【输入】

输入文件名为kth.in。

       第一行两个数n和k

第二行,n个数。(0<=每个数<231

【输出】

输出文件名为kth.out。

一个数表示答案。

【输入输出样例】

kth.in

kth.out

4 3

3 1 2 4

2

 

【样例解释】

[l,r]表示区间l~r的值

[1,1]:3

[2,2]:1

[3,3]:2

[4,4]:4

[1,3]:2

[2,4]:2

【数据说明】

对于30%的数据,1<=n<=100;

对于60%的数据,1<=n<=300

对于80%的数据,1<=n<=1000

对于100%的数据,1<=n<=100000, k<=奇数区间的数

 

 1 /*
 2 二分答案t,统计中位数大于等于t的区间有多少个。
 3 设a[i]为前i个数中有a[i]个数>=t,
 4 若奇数区间[l,r]的中位数>=t,则(a[r]-a[l-1])*2>r-l+1,即(a[r]*2-r)>(a[l-1]*2-l+1)。
 5 设b[i]=a[i]*2-i,统计每个b[i]有多少个b[j]<b[i] (j<i 且 j和i奇偶性不同)
 6 总复杂度O(nlognlogn)
 7 */
 8 #include <algorithm>
 9 #include <cstring>
10 #include <cstdio>
11 
12 #define max(a,b) (a>b?a:b)
13 
14 inline void read(int &x)
15 {
16     x=0; register char ch=getchar();
17     for(; ch>'9'||ch<'0'; ) ch=getchar();
18     for(; ch>='0'&&ch<='9'; ch=getchar()) x=x*10+ch-'0';
19 }
20 
21 const int N(100005);
22 
23 int n,k,a[N],num[N];
24 
25 
26 int l,r,mid,ans;
27 int tot[2][N<<1];
28 
29 #define lowbit(x) (x&((~x)+1))
30 inline void Update(int op,int x)
31 {
32     for(; x<=n<<1; x+=lowbit(x)) tot[op][x]++; 
33 }
34 inline int Query(int op,int x)
35 {
36     int ret=0;
37     for(; x; x-=lowbit(x)) ret+=tot[op][x];
38     return ret;
39 }
40 
41 inline bool check(int x)
42 {
43     int ret=0,sum=0,cnt=0;
44     memset(tot,0,sizeof(tot));
45     Update(0,n);
46     for(int i=1; i<=n; ++i)
47     {
48         sum+=(a[i]>=x);
49         cnt=sum<<1,cnt+=n-i;
50         ret+=Query(i&1,cnt);
51         Update(i+1&1,cnt);
52     }
53     return ret>k;
54 }
55 
56 int Presist()
57 {
58     read(n),read(k);
59     for(int i=1; i<=n; ++i)
60         read(a[i]),num[i]=a[i];
61     std::sort(num+1,num+n+1);
62     for(int i=1; i<=n; ++i)
63       if(num[i]!=num[i-1])
64          num[++num[0]]=num[i];
65     for(l=0,r=num[0]+1; l<=r; )
66     {
67         mid=l+r>>1;
68         if(check(num[mid]))
69         {
70             ans=mid;
71             l=mid+1;
72         }
73         else r=mid-1;
74     }
75     printf("%d\n",num[ans]);
76     return 0;
77 }
78 
79 int Aptal=Presist();
80 int main(int argc,char**argv){;} 
AC

 

 

 

 

 

 

3. 区间求和

(sum.cpp/c/pas)

时间限制:2s

内存限制:256MB

【问题述】

    有n个数,给定一个k,求所有长度大于等于k的区间中前k大数的总和。这样就比较简单相信大家都会,所以此题要求当k=1~n的总和,即求

 

【输入】

输入文件名为sum.in。

输入五个数n,a1,A,B,C。a1表示第一个数,A,B,C用来生成其余n-1个数。a(i)=(a(i-1)*A+B)mod C。1<=n<=1,000,000,0<=a1,A,B,C<=1,000,000,000

【输出】

输出文件名为sum.out。

一个数表示答案,最后答案对1,000,000,007取模。

 

【输入输出样例】

sum.in

sum.out

3 3 1 1 10

63

 

样例解释】

三个数为3,4,5

K=1:[1,1]=3,[1,2]=[2,2]=4,[1,3]=[2,3]=[3,3]=5

(表示各个区间在k=1时的答案)

K=2:[1,2]=7,[2,3]=[1,3]=9

K=3:[1,3]=12

【数据说明】

对于30%的数据,1<=n<=100

对于60%的数据,1<=n<=300

对于80%的数据,1<=n<=1000

对于100%的数据,1<=n<=1000000

 

模拟瞎暴力60分做法,枚举左右端点,得到k个最大数的和

设区间[l,r]的贡献为sum,只考虑K取不同值时整个区间的贡献,

新加一个a[r+1],设[l,r]中小于a[r+1]的数有x个,大于a[r+1]的数的和为y

a[r+1]使[l,r+1]多了a[r+1]*(x+1),因为统计不比他大的数会统计(x+1)次

这样子推一下

 

(因为比自己小的数与自己在同一区间内会增加自己被加的次数,所以统计所有比自己小的数有多少次在同一区间)对于上式的第一部分可以统计每个数前面比他小的数所在的位置总和,然后*a[j]*(n−j+1)即可,这可以按权值从小到大考虑每个数,然后用树状数组维护。第二部分类似,第三部分枚举一遍即可。

 

 1 #include <algorithm>
 2 #include <cstdio>
 3 
 4 inline void read(int &x)
 5 {
 6     x=0; register char ch=getchar();
 7     for(; ch>'9'||ch<'0'; ) ch=getchar();
 8     for(; ch>='0'&&ch<='9'; ch=getchar()) x=x*10+ch-'0';
 9 }
10 
11 const int mod(1e9+7);
12 const int N(1100000);
13 std::pair<int,int>a[N];
14 
15 int n,A,B,C,ans;
16 
17 int sum[N][2];
18 #define lowbit(x) (x&((~x)+1))
19 inline void Update(int i,int x,int op)
20 {
21     sum[0][op]+=x,sum[0][op]-=sum[0][op]>=mod?mod:0;
22     for(; i<=n; i+=lowbit(i))
23         sum[i][op]+=x,sum[i][op]-=sum[i][op]>=mod?mod:0;
24 }
25 inline int Query(int i,int op)
26 {
27     int ret=0;
28     for(; i; i-=lowbit(i))
29         ret+=sum[i][op],ret-=ret>=mod?mod:0;
30     return ret;
31 }
32 
33 int Presist()
34 {
35     read(n),read(a[1].first),read(A),read(B),read(C);
36     a[1].second=1;
37     for(int i=2; i<=n; ++i)
38     {
39         a[i].second=i;
40         a[i].first=(1ll*a[i-1].first*A+1ll*B)%C;
41     }
42     std::sort(a+1,a+n+1);
43     for(register int t1,t2,t3,i=1; i<=n; ++i)
44     {
45         t1=Query(a[i].second,0);
46         t2=sum[0][1]-Query(a[i].second-1,1);
47         t2+=mod; if(t2<0) t2+=mod;
48         t3=(1ll*t1*(n-a[i].second+1)+1ll*a[i].second*t2)%mod;
49         t3=(t3+1ll*a[i].second*(n-a[i].second+1))%mod;
50         ans=(ans+1ll*a[i].first*t3)%mod;
51         Update(a[i].second,a[i].second,0);
52         Update(a[i].second,n-a[i].second+1,1);
53     }
54     printf("%d",ans);
55     return 0;
56 }
57 
58 int Aptal=Presist();
59 int main(int argc,char**argv){;}
AC

 

转载于:https://www.cnblogs.com/Shy-key/p/7635139.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值