10.30上午考试
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的阶乘质因数分解后 如果一个素数次数是奇数那么不选这个素数 否则选这个素数 这样就能保证最大并且不会出现一个数的一部分选一部分不选的情况 因为不选的一定是素数 */ #include<iostream> #include<cstdio> #include<cstring> #define LL long long #define maxn 5000010 #define mod 100000007 using namespace std; LL n,tot,ans=1; LL prime[maxn],f[maxn],a[maxn]; LL init() { LL x=0,f=1;char c=getchar(); while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();} while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();} return x*f; } void prepare() { for(int i=2;i<=n;i++) { if(!f[i])prime[++tot]=i; for(int j=1;j<=tot&&prime[j]*i<=n;j++) { f[prime[j]*i]=1; if(i%prime[j]==0)break; } } } LL pow(LL x,LL m) { if(m==0)return 1; LL he=pow(x,m/2); he=(he*he)%mod; if(m&1)he=(he*x)%mod; return he; } int main() { freopen("hao.in","r",stdin); freopen("hao.out","w",stdout); n=init(); prepare(); for(int i=1;i<=tot;i++) { LL ha=n; while(ha) { a[i]+=ha/prime[i]; ha/=prime[i]; } } for(int i=1;i<=tot;i++) ans=(ans*pow(prime[i],a[i]/2*2))%mod; cout<<ans<<endl; return 0; }
【问题描述】
有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。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
/* 维护前缀和 O(n2)暴力 30分 */ #include<iostream> #include<cstdio> #include<cstring> #define LL long long #define maxn 500010 using namespace std; LL n,l,r,x,y; LL a[maxn],s[maxn]; LL init() { LL x=0,f=1;char c=getchar(); while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();} while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();} return x*f; } LL GCD(LL a,LL b) { return b==0?a:GCD(b,a%b); } int main() { freopen("jian.in","r",stdin); freopen("jian.out","w",stdout); n=init();l=init();r=init(); for(LL i=1;i<=n;i++) { a[i]=init(); s[i]=s[i-1]+a[i]; } for(LL i=1;i<=n;i++) { for(LL j=i;j<=n;j++) { double sum=s[j]-s[i-1]; if(sum>=l*(j-i+1)&&sum<=r*(j-i+1))x++; } } y=n*(n+1)/2; if(x%y==0) cout<<x/y<<endl; else { LL gcd=GCD(x,y); cout<<x/gcd<<"/"<<y/gcd<<endl; } return 0; }
/* 要求 区间平均值>=l&&<=r 的个数 即 现在我们来求区间平均值在1~r的个数和1~l(不包括l)的个数 前减后即为所求 以求1~r为例 (a[i]+a[i+1]+......+a[i+k-1])/k<=r (a[i]+a[i+1]+......+a[i+k-1])<=k*r (a[i]+a[i+1]+......+a[i+k-1])-k*r<=0 (a[i]-r)+(a[i+1]-r)+......+(a[i+k-1]-r)<=0 令c[i]=a[i]-r得到一个新数组c 即求c数组区间和<=0的个数 令s为数组c的前缀和数组 c[i]+c[i+1]+...+c[i+k-1]<=0 s[i+k-1]-s[i]<=0 s[i+k-1]<=s[i] 则 i<i+k-1 s[i]>=s[i+k-1] 即求s数组逆序对数 */ #include<iostream> #include<cstdio> #include<cstring> #define maxn 500010 using namespace std; int n,ansl,ansr,L,R; int a[maxn],b[maxn],c[maxn],s[maxn]; int init() { int x=0,f=1;char c=getchar(); while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();} while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();} return x*f; } void M_sort(int l,int r) { if(l>=r)return; int mid=(l+r)/2; M_sort(l, mid ); M_sort(mid+1,r); int i=l,j=mid+1,k=l-1; while(i<=mid&&j<=r) { if(b[i]>b[j]) { s[++k]=b[j++]; ansl+=mid-i+1; } else { s[++k]=b[i++]; } } while(i<=mid) s[++k]=b[i++]; while(j<=r) s[++k]=b[j++]; for(int i=l;i<=r;i++)b[i]=s[i]; } void m_sort(int l,int r) { if(l>=r)return; int mid=(l+r)/2; m_sort(l, mid ); m_sort(mid+1,r); int i=l,j=mid+1,k=l-1; while(i<=mid&&j<=r) { if(c[i]>=c[j]) { s[++k]=c[j++]; ansr+=mid-i+1; } else { s[++k]=c[i++]; } } while(i<=mid) s[++k]=c[i++]; while(j<=r) s[++k]=c[j++]; for(int i=l;i<=r;i++)c[i]=s[i]; } int gcd(int a,int b) { return b==0?a:gcd(b,a%b); } int main() { freopen("jian.in","r",stdin); freopen("jian.out","w",stdout); n=init();L=init();R=init(); for(int i=1;i<=n;i++) a[i]=init(); for(int i=1;i<=n;i++) { b[i]=b[i-1]+a[i]-L; if(b[i]<0)ansl++; } for(int i=1;i<=n;i++) { c[i]=c[i-1]+a[i]-R; if(c[i]<=0)ansr++; } M_sort(1,n); m_sort(1,n); int A=ansr-ansl,B=n*(n+1)/2; if(A%B==0)cout<<A/B<<endl; else { int g=gcd(A,B); cout<<A/g<<"/"<<B/g<<endl; } return 0; }
【问题描述】
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。
搜索题
45分:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
/* O(k的n次方) 无任何剪枝超时 45分 */ #include<iostream> #include<cstdio> #include<cstring> using namespace std; int m,w,n,ans=0x7ffffff; struct node { int x; int y; }a[20]; int c[20][20]; int init() { int x=0,f=1;char c=getchar(); while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();} while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();} return x*f; } void work1() { int minx=10000,maxx=0,miny=10000,maxy=0; for(int i=1;i<=n;i++) { minx=min(minx,a[i].x); miny=min(miny,a[i].y); maxx=max(maxx,a[i].x); maxy=max(maxy,a[i].y); } printf("%d\n",2*(maxx-minx+1+maxy-miny+1)); } void dfs(int x) { if(x==n+1) { int sum=0; for(int i=1;i<=w;i++) { int minx=10000,maxx=0,miny=10000,maxy=0; for(int j=1;j<=c[i][0];j++) { int t=c[i][j]; minx=min(minx,a[t].x); miny=min(miny,a[t].y); maxx=max(maxx,a[t].x); maxy=max(maxy,a[t].y); } if(c[i][0])sum+=2*(maxx-minx+1+maxy-miny+1); } ans=min(ans,sum); return ; } for(int i=1;i<=w;i++) { c[i][0]++;c[i][c[i][0]]=x; dfs(x+1); c[i][0]--; } } int main() { freopen("dan.in","r",stdin); freopen("dan.out","w",stdout); m=init();w=init();n=init(); for(int i=1;i<=n;i++) a[i].x=init(),a[i].y=init(); if(w==1) { work1(); return 0; } dfs(1); printf("%d\n",ans); return 0; }
95分:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
/* 各种骗分 骗到95分 */ #include<iostream> #include<cstdio> #include<cstring> #include<ctime> #include<algorithm> #include<cstdlib> using namespace std; int m,w,n,ans=0x7ffffff; struct node { int x; int y; }a[20]; int minx[20],miny[20],maxx[20],maxy[20],f[20]; int init() { int x=0,f=1;char c=getchar(); while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();} while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();} return x*f; } void dfs(int x) { if(clock()>1960){ printf("%d",ans); exit(0); } int sum=0,tot=0; for(int i=1;i<=w;i++) if(f[i])sum+=2*(maxx[i]-minx[i]+1+maxy[i]-miny[i]+1); if(sum>=ans)return; if(x==n+1) { ans=sum; return ; } for(int i=1;i<=w;i++) { int tx=minx[i],ty=miny[i]; int rx=maxx[i],ry=maxy[i]; minx[i]=min(minx[i],a[x].x); miny[i]=min(miny[i],a[x].y); maxx[i]=max(maxx[i],a[x].x); maxy[i]=max(maxy[i],a[x].y); f[i]++; dfs(x+1); minx[i]=tx;miny[i]=ty; maxx[i]=rx;maxy[i]=ry; f[i]--; } } int main() { freopen("dan.in","r",stdin); freopen("dan.out","w",stdout); m=init();w=init();n=init(); for(int i=1;i<=n;i++) a[i].x=init(),a[i].y=init(); //random_shuffle(a+1,a+n+1); memset(minx,127/3,sizeof(minx)); memset(miny,127/3,sizeof(miny)); dfs(1); printf("%d\n",ans); return 0; }
正解:暂无