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
#include<cstdio> #include<cstring> #include<cstdlib> #include<iostream> #include<algorithm> #define N 1000010 #define LL long long using namespace std; bool vis[N]; int n,m,x; int read() { int x=0,f=1; char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1; char ch=getchar();} while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar(); return x*f; } int main() { freopen("count.in","r",stdin); freopen("count.out","w",stdout); n=read(),m=read(); int j,ans=n;LL s; for(int i=1;i<=m;i++) { x=read(),j=1,s=0; while(s<n) { s=(LL)x*(LL)j;j++; if(s<=n&&!vis[s]) ans--,vis[s]=true; } } printf("%d",ans); return 0; }
容斥原理+搜索
都会容斥原理吧,有一个数的时候为+,两个数的时候为- ,三个数的时候+、、、总的来说就是奇数的时候为+偶数的时候为-。(这不废话吗、、)
不是这些数的倍数的数的个数为总共的-每一个数的的倍数的个数+两两的倍数的个数(即为这两个数最小公倍数的倍数的个数)-每三个数的公共倍数的个数(这三个数的最小公倍数的倍数个数)、、、、
a和b最小公倍数=a*b/gcd(a,b) ,n以内a的倍数的个数为n/a
我们用搜索判断这个数选不选,选的话数的个数+1,与原来的符号就相反,反之就相同,然后进行下一轮搜索
#include<cstdio> #include<cstdlib> #include<cstring> #include<iostream> #include<algorithm> #define N 50 #define LL long long using namespace std; int n,m,a[N]; long long ans; int read() { int x=0,f=1; char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar(); return x*f; } void dfs(int f,int cnt,LL sum) { if(sum>n) return ; if(cnt==m+1) { ans+=n/sum*f; return ; } dfs(-f,cnt+1,sum*(LL)a[cnt]/__gcd(sum,(LL)a[cnt])); dfs(f,cnt+1,sum); } int main() { n=read(),m=read(); for(int i=1;i<=m;i++) a[i]=read(); dfs(1,1,1); printf("%lld",ans); return 0; }
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<=奇数区间的数
#include<cstdio> #include<cstdlib> #include<cstring> #include<iostream> #include<algorithm> #define N 1010 using namespace std; int n,k,now,s,a[N],q[N*N],tmp[N]; int read() { int x=0,f=1; char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1; ch=getchar();} while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar(); return x*f; } int cmp(int a,int b){return a>b;} int main() { freopen("kth.in","r",stdin); freopen("kth.out","w",stdout); n=read(),k=read(); for(int i=1;i<=n;i++) a[i]=read(); for(int i=1;i<=n;i++) { now=0; for(int j=i;j<=n;j++) { tmp[++now]=a[j]; if(now%2==0) continue; sort(tmp+1,tmp+1+now); q[++s]=tmp[now/2+1]; } } sort(q+1,q+1+s,cmp); printf("%d",q[k]); }
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
#include<cstdio> #include<cstring> #include<cstdlib> #include<iostream> #include<algorithm> #define N 1010 #define mod 1000000007 #define LL long long using namespace std; long long ans,a[N],tmp[N]; int n,A,B,C,now; int read() { int x=0,f=1; char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1; char ch=getchar();} while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar(); return x*f; } LL cmp(LL a,LL b){return a>b;} int main() { freopen("sum.in","r",stdin); freopen("sum.out","w",stdout); n=read(),a[1]=read(); A=read(),B=read(),C=read(); for(int i=2;i<=n;i++) a[i]=(a[i-1]*A%C+B%C)%C; for(int i=1;i<=n;i++) { now=0; for(int j=i;j<=n;j++) { tmp[++now]=a[j]; sort(tmp+1,tmp+1+now,cmp); for(int k=1;k<=now;k++) ans=(ans%mod+tmp[k]*(now-k+1)%mod)%mod; } } printf("%lld",ans%mod); return 0; }