济南-1030试题解题报告
济南-1030试题解题报告
By shenben
本解题报告解析均为100分解题思路。
上午
T1
题意:从1− n中找一些数乘起来使得答案是一个完全平方数,求这个完全平方数
最大可能是多少.
解析:
1、 质因数分解
2、 1->n用质因数指数的相加的形式将1*n累乘起来
3、 扫一遍指数为奇数的质因数都-1,偶数的不变
4、 快速幂乘一遍,同时取模
T2
题意:有n个数,随机选择一段区间,如果这段区间的所有数的平均值在[L,R]中则
你比较厉害。求你比较厉害的概率
解析:(暴力枚举 40分)
100分需要推式子,过程略,最后式子:求S[R]-S[L]
(S[x]=前缀和a[i]-x的逆序对个数)
Fz= S[R]-S[L];
Fm=(n+1)*n/2;
Fz=fm-fz;
Ans=fz/fm(需要约分)
T3
题意:n*m的方阵上有?棵葱,你要修一些栅栏把它们围起来。一个栅栏是一段
沿着网格建造的封闭图形(即要围成一圈) 。各个栅栏之间应该不相交、不重叠
且互相不包含。如果你最多修?个栅栏,那么所有栅栏的长度之和最小是多少
解析:
搜索+各种剪枝
详见代码
下午
T1
题意:
一张长度为n的纸带,我们可以从左至右编号为0 −n(纸带最左端标号为
0) 。现在有m次操作,每次将纸带沿着某个位置进行折叠,问所有操作之后纸带
的长度是多少
解析:
模拟
折痕左边大,右边往左边折,同时右边向左边映射.L不变,R=折痕
折痕右边大,左边往右边折,同时左边向右边映射.L=折痕,R不变
(100分不能用并查集维护,应为并查集依靠数组的size太大)
T2
题意:给你 L,R,S,M,求满足L<=(S*x) mod M<=R最小的正整数x
解析:
略
详见代码
T3
题意:n个人坐成一圈,其中第k个人拿着一个球。每次每个人会以一定的概率向左边的人和右边的人传球。当所有人都拿到过球之后,最后一个拿到球的人即为胜者。求第n个人获胜的概率(所有人按照编号逆时针坐成一圈)
解析:
等比数列(还是推式子)
上午
T1代码:
#include<cstdio> #include<cstring> #define ll long long #define mod 100000007 using namespace std; const int N=5e6+10; int n,tot,prime[N]; bool check[N]; void prepare(){ for(int i=2;i<=n;i++){ if(!check[i]) prime[++tot]=i; for(int j=1;j<=tot&&prime[j]*i<=n;j++){ check[prime[j]*i]=1; if(i%prime[j]==0) break; } } } #define name "hao" int main(){ freopen(name".in","r",stdin); freopen(name".out","w",stdout); scanf("%d",&n); prepare(); memset(check,0,sizeof check); for(ll res,i=1;i<=tot;i++){ res=0; for(ll j=prime[i];j<=n;j*=(ll)prime[i]) res+=n/j; if(res&1) check[prime[i]]=1; } ll ans=1; for(ll i=2;i<=n;i++) if(!check[i]) ans=ans*i%mod; printf("%I64d",ans); fclose(stdin); fclose(stdout); return 0; }
T2代码:
#include<cstdio> #include<cstring> #include<algorithm> #define name "jian" #define ll long long #ifdef unix #define LL "%lld" #else #define LL "%I64d" #endif using namespace std; const int N=1e6+10; int n,L,R,a[N],b[N]; ll fz,fm,gy,ans,s[N],c[N]; inline const int read(){ register int x=0,f=1; register char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();} return x*f; } void binary_chop(int l,int r){ if(l==r) return ; int mid=l+r>>1; binary_chop(l,mid);binary_chop(mid+1,r); int p=l,q=l,j=mid+1; while(p<=mid&&j<=r){ if(s[p]>s[j]){ ans+=mid-p+1; c[q++]=s[j++]; } else{ c[q++]=s[p++]; } } while(p<=mid) c[q++]=s[p++]; while(j<=r) c[q++]=s[j++]; for(int i=l;i<=r;i++) s[i]=c[i]; } int main(){ freopen(name".in","r",stdin); freopen(name".out","w",stdout); n=read();L=read();R=read(); for(int i=1;i<=n;i++) a[i]=read(); for(int i=1;i<=n;i++) b[i]=a[i]-L; for(int i=1;i<=n+1;i++) s[i]=s[i-1]+b[i-1]; binary_chop(1,n+1);fz+=ans; memset(s,0,sizeof s);ans=0; for(int i=1;i<=n;i++) b[i]=a[i]-R; for(int i=1;i<=n+1;i++) s[i]=s[i-1]+b[i-1]; reverse(s+1,s+n+2); binary_chop(1,n+1);fz+=ans; fm=(ll)n*(n+1)/2; fz=fm-fz; gy=__gcd(fz,fm); fz/=gy;fm/=gy; if(fm==1) printf(LL"\n",fz); else printf(LL "/" LL,fz,fm); fclose(stdin); fclose(stdout); return 0; } /* 40分代码,长个记性 #include<cstdio> #include<cstring> #include<algorithm> using namespace std; #define name "jian" #define ll long long #ifdef unix #define LL "%lld" #else #define LL "%I64d" #endif inline const ll read(){ register ll x=0,f=1; register char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();} return x*f; } const int N=5e5+10; int n,p,L,R,a[N]; ll sum[N]; ll fz,fm,gy; int main(){ freopen(name".in","r",stdin); freopen(name".out","w",stdout); n=read();L=read();R=read(); for(int i=1;i<=n;i++) a[i]=read(); for(int i=1;i<=n;i++) sum[i]=sum[i-1]+a[i]; fm=(ll)(n+1)*n/2; double tmp; for(int i=1;i<=n;i++){ for(int j=i;j<=n;j++){ tmp=(double)(sum[j]-sum[i-1])/(j-i+1);//必须用double类型(除法有精度要求),否则会炸 //当时脑残了,还去排序,这是一个数列。连四十分都没有拿到。QAQ if(tmp>=L&&tmp<=R) fz++;//直接判是否在[L,R]中就好了 } } gy=__gcd(fz,fm); fz/=gy;fm/=gy; if(fm==1) printf(LL"\n",fz); else printf(LL "/" LL,fz,fm); fclose(stdin); fclose(stdout); return 0; } */
T3代码:
#include<cstdio> #include<algorithm> using namespace std; inline const int read(){ register int x=0,f=1; register char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();} return x*f; } const int N=1e6+10; const int M=20; int m,n,k,xx[M],yy[M]; int cost[N],s[M]; int tot,nowmask,answer,full; struct rect{ int x1,x2,y1,y2; int mask,w; rect(){} rect(int _x1,int _y1,int _x2,int _y2){ x1=_x1,y1=_y1,x2=_x2,y2=_y2; mask=0; for(int i=0;i<n;i++) if(x1<=xx[i]&&xx[i]<=x2&&y1<=yy[i]&&yy[i]<=y2) mask|=(1<<i); w=((x2-x1+1)+(y2-y1+1))*2; if(mask==full) answer=w; } }a[N]; void dfs(int cnt,int j,int cost){ if(nowmask==full){ //if(clock()>=1950){printf("%d",answer);exit(0);} answer=min(answer,cost);return ; } if(cnt>=k||j>tot||cost>=answer) return ; for(int i=j;i<=tot;i++){ if(nowmask&a[i].mask) continue; nowmask^=a[i].mask; dfs(cnt+1,i+1,cost+a[i].w); nowmask^=a[i].mask; } } void DFS(int now,int cnt,int res){ if(now==n){ if(res<answer) answer=res;return; } if(res+(k-cnt)*4>=answer) return; for(int i=1;i<=cnt;i++){ int pres=s[i]; s[i]|=(1<<now); DFS(now+1,cnt,res-cost[pres]+cost[s[i]]); s[i]^=(1<<now); } if(cnt<k){ s[++cnt]=(1<<now); DFS(now+1,cnt,res+4); } } #define name "dan" int main(){ freopen(name".in","r",stdin); freopen(name".out","w",stdout); m=read();k=read();n=read(); full=(1<<n)-1; for(int i=0;i<n;i++) xx[i]=read(),yy[i]=read(); if(n<15){ for(int i=0;i<n;i++){ for(int j=i;j<n;j++){ for(int k=j;k<n;k++){ for(int l=k;l<n;l++){ a[++tot]=rect(min(min(xx[i],xx[j]),min(xx[k],xx[l])),min(min(yy[i],yy[j]),min(yy[k],yy[l])), max(max(xx[i],xx[j]),max(xx[k],xx[l])),max(max(yy[i],yy[j]),max(yy[k],yy[l]))); } } } } nowmask=0; dfs(0,1,0); printf("%d",answer); } else{ answer=4000; for(int i=1;i<=full;i++){ int sx=1001,mx=-1,sy=1001,my=-1; for(int j=0;j<n;j++){ if((i>>j)&1){ if(xx[j]<sx) sx=xx[j]; if(xx[j]>mx) mx=xx[j]; if(yy[j]<sy) sy=yy[j]; if(yy[j]>my) my=yy[j]; } } cost[i]=(mx-sx+1)*2+(my-sy+1)*2; } DFS(0,0,0); printf("%d",answer); } fclose(stdin); fclose(stdout); return 0; }
下午
T1代码:
#include<iostream> #include<cstdio> #define ll long long #define name "he" #ifdef unix #define LL "%lld" #else #define LL "%I64d" #endif using namespace std; const int N=1e4+10; ll f[N],n,L,R; int m; inline const ll read(){ register ll x=0,f=1; register char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();} return x*f; } int main(){ freopen(name".in","r",stdin); freopen(name".out","w",stdout); n=read();m=read(); L=0;R=n; for(int i=1;i<=m;i++) f[i]=read(); for(int i=1;i<=m;i++){ if(f[i]*2>=L+R) R=f[i];//舍掉右边 else L=f[i];//舍掉左边 for(int j=i+1;j<=m;j++){ if(f[j]>R) f[j]=R*2-f[j]; if(f[j]<L) f[j]=L*2-f[j]; } } printf(LL,R-L); return 0; } /*60分代码存档 #include<cstdio> #define name "he" using namespace std; inline const int read(){ register int x=0,f=1; register char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();} return x*f; } const int N=1e6+10; int n,m,a[N],fa[N]; inline const int ABS(int x){ return x>0?x:-x; } int find(int x){ return fa[x]==x?x:fa[x]=find(fa[x]); } int main(){ freopen(name".in","r",stdin); freopen(name".out","w",stdout); n=read();m=read(); for(int i=1;i<=m;i++) a[i]=read(); int starting=0,ending=n; for(int i=0;i<=n;i++) fa[i]=i; for(int i=1,j,k,t1,t2,fx,fy;i<=m;i++){ a[i]=find(a[i]); t1=ABS(a[i]-starting); t2=ABS(a[i]-ending); if(t1<t2){ for(j=a[i]-1,k=a[i]+1,fx,fy;j>=starting;j--,k++){ fx=find(j); fy=find(k); fa[fx]=fy; } starting=a[i]; } else{ for(j=a[i]+1,k=a[i]-1;j<=ending;j++,k--){ fx=find(j); fy=find(k); fa[fx]=fy; } ending=a[i]; } } printf("%d",ending-starting); return 0; } */
T2代码:
//copy from other's #include<cstdio> #include<algorithm> using namespace std; const int N=1e5+10; int a[N],top; int erfen(int x){ int l=1,r=top,mid,res=0; while(l<=r){ mid=(l+r)>>1; if(a[mid]>=x) res=mid,r=mid-1; else l=mid+1; } return res; } int main(){ freopen("she.in","r",stdin); freopen("she.out","w",stdout); int i,j,k,n,m,s,l,r,x,now,t,ans,ans2; bool fl; scanf("%d",&t); while(t--){ scanf("%d%d%d%d",&m,&s,&l,&r); if(l>=m){printf("-1\n");continue;} if(r>=m)r=m-1; now=0;fl=0; top=0; for(n=1;n*n<=m;n++){ now=(now+s)%m; if(l<=now&&now<=r){ printf("%d\n",n); fl=1;break; } a[++top]=now; } --n; int ste=a[top]; if(fl) continue; sort(a+1,a+top+1); for(now=1;now*n<=m;now++){ l=(l-ste+m)%m;r=(r-ste+m)%m; if(l>r) { if(a[top]>=l){fl=1;break;} if(a[1]<=r){fl=1;break;} } else{ if(a[top]<l) continue; int x=erfen(l); if(a[x]<=r){fl=1;break;} } } if(!fl){printf("-1\n");continue;} ans=now*n; now=0; for(i=1;i<=top;i++){ now=(now+s)%m; if(l<=now&&now<=r)break; } ans+=i; printf("%d\n",ans); } return 0; } /*30分代码存档 #include<cstdio> #include<ctime> #include<cstdlib> #include<iostream> #include<algorithm> #include<cstring> #include<cmath> #define ll long long #define name "she" using namespace std; inline const ll read(){ register ll x=0,f=1; register char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();} return x*f; } ll cas,tx,m,s,l,r; ll sx=1e6+10; bool falg; void go(int tt){ tt++; while(tt--) puts("-1"); exit(0); } int main(){ freopen(name".in","r",stdin); freopen(name".out","w",stdout); cas=read(); while(cas--){ m=read();s=read();l=read();r=read(); if(m<=l){puts("-1");continue;} if(clock()>=900) go(cas); if(l==r) tx=m*10,falg=1; for(ll i=1;i<=sx;i++){ if(clock()>=900) go(cas); if(falg){ if(i>tx){ puts("-1"); falg=0; break; } } ll tmp=s*i%m; if(tmp>=l&&tmp<=r){ printf("%d\n",(int)i); break; } if(tmp==1&&i>m){ puts("-1"); break; } } } return 0; } */
T3代码:
#include<cstdio> #define LDB long double #define DB double using namespace std; const int N=1000+10; int T,n,k,pre[N],next[N]; LDB p[N],q[N]; void deal(int b){ int a=pre[b],c=next[b]; LDB pa=p[a],pb=p[b],pc=p[c]; p[a]=pa*pb/(1-pa*(1-pb)); q[a]=1-p[a]; q[c]=(1-pc)*(1-pb)/(1-pb*(1-pc)); p[c]=1-q[c]; next[a]=c;pre[c]=a; } LDB solve(){ if(n<=2) return 1; if(n<=3) return k==1?p[1]:q[2]; for(int i=1;i<=n;i++) pre[i]=i-1,next[i]=i+1; pre[1]=n;next[n]=1; if(k==1){ for(int i=2;i<n-1;i++) deal(i); return p[1]; } if(k==n-1){ for(int i=2;i<n-1;i++) deal(i); return q[n-1]; } for(int i=2;i<n-1;i++) if(i!=k) deal(i); deal(k); return q[k]*p[1]+p[k]*q[n-1]; } DB v; #define name "it" int main(){ freopen(name".in","r",stdin); freopen(name".out","w",stdout); scanf("%d",&T); while(T--){ scanf("%d%d",&n,&k); for(int i=1;i<=n;i++){ scanf("%lf",&v); p[i]=v; q[i]=1-v; } printf("%.9lf\n",(DB)solve()); } fclose(stdin); fclose(stdout); return 0; } /*可骗30分代码存档 #include<cstdio> const int MAXN=110; double p[MAXN]; int n=0,k=0; void solve() { for(int i=1;i<=n;i++) scanf("%lf",p+i); p[0]=p[n]; if(n==1) printf("%.9lf\n",1.0); else if(n==k) printf("%.9lf\n",0.0); else if(n==2) printf("%.9lf\n",1.0); else printf("%.9lf\n",k==1?p[1]:(1-p[2])); } int main() { freopen("it.in","r",stdin); freopen("it.out","w",stdout); int T=0; scanf("%d\n",&T); while(T--){ scanf("%d%d",&n,&k); solve(); } return 0; }*/
P75
竞赛时间: ????年??月??日??:??-??:??
注意事项(请务必仔细阅读)
【 问题描述】
从1 −
N中找一些数乘起来使得答案是一个完全平方数,求这个完全平方数
最大可能是多少。
【输入格式】
第一行一个数字N。
【输出格式】
一行一个整数代表答案对100000007取模之后的答案。
【样例输入】
7
【样例输出】
144
【样例解释】
但是塔外面有东西。
【数据规模与约定】
对于20%的数据, 1 ≤ N ≤ 100。
对于50%的数据, 1 ≤ N ≤ 5000。
对于70%的数据, 1 ≤ N ≤ 105。
对于100%的数据, 1 ≤ N ≤ 5 × 106。
【问题描述】
有N个数,随机选择一段区间,如果这段区间的所有数的平均值在[𝑙, 𝑟]中则你比较厉害。求你比较厉害的概率。
【输入格式】
第一行有三个数N, l, r,含义如上描述。
接下来一行有N个数代表每一个数的值。
【输出格式】
输出一行一个分数a/b代表答案,其中a, b互质。 如果答案为整数则直接输出该
整数即可。
【样例输入 1】
4 2 3
3 1 2 4
【样例输出 1】
7/10
【样例输入 2】
4 1 4
3 1 2 4
【样例输出 2】
1
【样例解释】
塔外面有棵树。
【数据规模与约定】
对于30%的数据, 1 ≤ N ≤ 104。
对于60%的数据, 1 ≤ N ≤ 105。
对于100%的数据, 1 ≤ N ≤ 5 × 105, 0 < l ≤ r ≤ 100。
【问题描述】
m × m的方阵上有n棵葱, 你要修一些栅栏把它们围起来。 一个栅栏是一段
沿着网格建造的封闭图形( 即要围成一圈)。 各个栅栏之间应该不相交、 不重叠
且互相不包含。 如果你最多修k个栅栏, 那么所有栅栏的长度之和最小是多少?
【 输入格式】
第一行三个整数m, k, n。
接下来n行每行两个整数x, y代表某棵葱的位置。
【 输出格式】
一行一个整数代表答案。
【样例输入 1】
6 1 4
1 3
4 2
4 4
6 4
【 样例输出 1】
18
【样例输入 2】
6 2 4
1 3
4 2
4 4
6 4
【 样例输出 2】
16
【 样例解释】
你猜树上有啥。
【数据规模与约定】
对于10%的数据, k = 1。
对于30%的数据, k ≤ 2。
对于60%的数据, n ≤ 10。
对于100%的数据, 1 ≤ k ≤ n ≤ 16, m ≤ 1000。
P76
竞赛时间: ????年??月??日??:??-??:??
题目名称 | 他 | 她 | 它 |
名称 | he | she | it |
输入 | he.in | she.in | it.in |
输出 | he.out | she.out | it.out |
每个测试点时限 | 1 秒 | 1 秒 | 1 秒 |
内存限制 | 512MB | 512MB | 512MB |
测试点数目 | 10 | 10 | 10 |
每个测试点分值 | 10 | 10 | 10 |
是否有部分分 | 无 | 无 | 无 |
题目类型 | 传统 | 传统 | 传统 |
他
【问题描述】
一张长度为N的纸带, 我们可以从左至右编号为0 − N( 纸带最左端标号为
0)。 现在有M次操作, 每次将纸带沿着某个位置进行折叠,
问所有操作之后纸带
的长度是多少。
【输入格式】
第一行两个数字N, M如题意所述。
接下来一行M个整数代表每次折叠的位置。
【输出格式】
一行一个整数代表答案。
【样例输入】
5 2
3 5
【样例输出】
2
【样例解释】
树上有只鸟。
【数据规模与约定】
对于60%的数据, N, M ≤ 3000。
对于100%的数据, N ≤ 10^18, M ≤ 3000。
她
【问题描述】
给你M, S, L, R, 求满足L ≤ (S × x) mod M ≤
R最小的正整数x。
【输入格式】
第一行一个数T代表数据组数。
接下来T行每行四个数代表该组数据的M, S, L, R。
【输出格式】
对于每组数据, 输出一行代表答案。 如果不存在解, 输出“ −1”。
【样例输入】
1
5 4 2 3
【 样例输出】
2
【 样例解释】
叫南小鸟。
【数据规模与约定】
对于30%的数据, 保证有解且答案不超过10^6。
对于另外20%的数据, L = R。
对于100%的数据, 1 ≤ T ≤ 100,0 ≤ M, S, L,R
≤ 10^9。
它
【问题描述】
N个人坐成一圈, 其中第K个人拿着一个球。 每次每个人会以一定的概率向
左边的人和右边的人传球。 当所有人都拿到过球之后, 最后一个拿到球的人即为
胜者。 求第N个人获胜的概率。( 所有人按照编号逆时针坐成一圈)
【输入格式】
第一行一个数T代表数据组数。
对于每组数据, 第一行两个整数N, K如题意所述。
接下来每行一个实数p代表该人将球传给右边的人的概率。
【输出格式】
对于每组数据, 一行一个实数代表答案, 保留9位小数。
【样例输入】
1
5 1
0.10
0.20
0.30
0.40
0.50
【 样例输出】
0.007692308
【 样例解释】
然后鸟是我的。
【数据规模与约定】
对于20%的数据, N ≤ 3。
对于70%的数据, T, N ≤ 100。
对于100%的数据, T ≤ 10000,1 ≤ N ≤ 100。