首页 > 代码库 > 10.30 morning
10.30 morning
P75
竞赛时间: ????年??月??日??:??-??:??
注意事项(请务必仔细阅读)
【 问题描述】
从1 − N中找一些数乘起来使得答案是一个完全平方数,求这个完全平方数
最大可能是多少。
【输入格式】
第一行一个数字N。
【输出格式】
一行一个整数代表答案对100000007取模之后的答案。
【样例输入】
7
【样例输出】
144
【样例解释】
但是塔外面有东西。
【数据规模与约定】
对于20%的数据, 1 ≤ N ≤ 100。
对于50%的数据, 1 ≤ N ≤ 5000。
对于70%的数据, 1 ≤ N ≤ 105。
对于100%的数据, 1 ≤ N ≤ 5 × 106。
/*数论题 筛素数的时候是到maxn不是n 然后就有了第一天6.2s的梗2333*/#include<iostream>#include<cstdio>#define maxn 5000010#define mod 100000007#define ll long longusing namespace std;ll n,prime[maxn/10],c[maxn/10],num,ans=1;bool f[maxn];void Prime(){ for(int i=2;i<=maxn-10;i++){//下次筛到n.... if(f[i]==0)prime[++num]=i; for(int j=1;j<=num;j++){ if(i*prime[j]>maxn-10)break; f[i*prime[j]]=1; if(i%prime[j]==0)break; } }}void Solve(){ for(int i=1;i<=num;i++){ ll P=prime[i]; if(P>n)break; while(n>=P){ c[i]+=n/P;P*=prime[i]; } }}ll Qc(ll a,ll b){ ll r=1; while(b){ if(b&1)r=r*a%mod; b>>=1;a=a*a%mod; } return r%mod;}int main(){ freopen("hao.in","r",stdin); freopen("hao.out","w",stdout); cin>>n; Prime();Solve(); for(int i=1;i<=num;i++) if(c[i]&1)c[i]--; for(int i=1;i<=num;i++){ if(prime[i]>n)break; ans=ans*Qc(prime[i],c[i])%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。
暴力30
/*暴力30*/#include<iostream>#include<cstdio>#define ll long long#define maxn 500010using namespace std;int l,r,s[maxn];ll cnt,n;int init(){ int x=0,f=1;char s=getchar(); while(s<‘0‘||s>‘9‘){if(s==‘-‘)f=-1;s=getchar();} while(s>=‘0‘&&s<=‘9‘){x=x*10+s-‘0‘;s=getchar();} return x*f;}ll gcd(ll x,ll y){ return y==0?x:gcd(y,x%y);}void Printf(ll a,ll b){ if(a==0)cout<<0<<endl; else if(b%a==0)cout<<b/a<<endl; else{ int G=gcd(b,a); a/=G;b/=G; cout<<a<<"/"<<b<<endl; }}int main(){ freopen("jian.in","r",stdin); freopen("jian.out","w",stdout); cin>>n;l=init();r=init(); int x;double k; for(int i=1;i<=n;i++){ x=init();s[i]=s[i-1]+x; } for(int i=1;i<=n;i++) for(int j=i;j<=n;j++){ k=(double)(s[j]-s[i-1])/(double)(j-i+1); if(k>=l&&k<=r)cnt++; } Printf(cnt,n*(n+1)/2); return 0;}
100
/*序列变化 然后就简单了求平均值在[l,r]内的不妨我们先求[1,l)的 在求[1,r]的 然后做差假设一段区间l-r 有al + al+1 + al+2 +...+ar <X*(r-l+1)-> al-X + al+1-X + al+2-X +...+ar-X <0令bi=ai-X si为bi的前缀和那就是求sr < sl-1 就是逆序对的个数然而我写的归并并不能求l==r的 但恰好这里是r l-1就很好地避免了这种情况注意l==1的时候 右边一项是0 所以特盘一下还有 L 和 R 略有不同 */#include<iostream>#include<cstdio>#define ll long long#define maxn 500010using namespace std;ll n,L,R,a[maxn],b[maxn],c[maxn],q[maxn],ans;ll init(){ ll x=0,f=1;char s=getchar(); while(s<‘0‘||s>‘9‘){if(s==‘-‘)f=-1;s=getchar();} while(s>=‘0‘&&s<=‘9‘){x=x*10+s-‘0‘;s=getchar();} return x*f;}void Msort1(ll l,ll r){ if(l>=r)return; ll i,j,k,mid=l+r>>1; Msort1(l,mid);Msort1(mid+1,r); i=l;j=mid+1;k=l; while(i<=mid&&j<=r){ if(b[i]>b[j]){ q[k++]=b[j++];ans-=(mid-i+1); } else q[k++]=b[i++]; } while(i<=mid)q[k++]=b[i++]; while(j<=r)q[k++]=b[j++]; for(int i=l;i<=r;i++)b[i]=q[i];}void Msort2(ll l,ll r){ if(l>=r)return; ll i,j,k,mid=l+r>>1; Msort2(l,mid);Msort2(mid+1,r); i=l;j=mid+1;k=l; while(i<=mid&&j<=r){ if(c[i]>=c[j]){ q[k++]=c[j++];ans+=(mid-i+1); } else q[k++]=c[i++]; } while(i<=mid)q[k++]=c[i++]; while(j<=r)q[k++]=c[j++]; for(int i=l;i<=r;i++)c[i]=q[i];}ll gcd(ll x,ll y){ return y==0?x:gcd(y,x%y);}void Printf(ll a,ll b){ if(a==0)cout<<0<<endl; else if(a%b==0)cout<<a/b<<endl; else{ int G=gcd(b,a); a/=G;b/=G; cout<<a<<"/"<<b<<endl; }}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(); b[i]=b[i-1]+a[i]-L; c[i]=c[i-1]+a[i]-R; if(c[i]<=0)ans++; if(b[i]<0)ans--; } Msort1(1,n);Msort2(1,n); Printf(ans,n*(n+1)/2); fclose(stdin);fclose(stdout); 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。
红果果的是50
然后卡时+剪枝95
/*最优性剪枝+卡时 蒙到了95 剩下的就不会了2333*/#include<cstdio>#include<cstring>#include<ctime>#include<cstdlib>#define maxn 110#define inf 1e9using namespace std;int n,m,k,x[maxn],y[maxn],ans=inf;int X1[maxn],X2[maxn],Y1[maxn],Y2[maxn];int min(int x,int y){ return x<y?x:y;}int max(int x,int y){ return x>y?x:y;}void Dfs(int now){ if(clock()>1950){ printf("%d\n",ans);exit(0); } int mx=0; for(int i=1;i<=k;i++){ if(X2[i]==X2[0])continue; mx+=(X1[i]-X2[i]+1+Y1[i]-Y2[i]+1)*2; } if(mx>=ans)return; if(now==m+1){ int mx=0; for(int i=1;i<=k;i++){ if(X2[i]==X2[0])continue; mx+=(X1[i]-X2[i]+1+Y1[i]-Y2[i]+1)*2; } ans=min(ans,mx); return; } for(int i=1;i<=k;i++){ int a=X1[i],b=Y1[i],c=X2[i],d=Y2[i]; X1[i]=max(X1[i],x[now]); Y1[i]=max(Y1[i],y[now]); Y2[i]=min(Y2[i],y[now]); X2[i]=min(X2[i],x[now]); Dfs(now+1); X1[i]=a;Y1[i]=b;X2[i]=c;Y2[i]=d; }}int main(){ freopen("dan.in","r",stdin); freopen("dan.out","w",stdout); scanf("%d%d%d",&n,&k,&m); memset(X2,127/3,sizeof(X2)); memset(Y2,127/3,sizeof(Y2)); for(int i=1;i<=m;i++) scanf("%d%d",&x[i],&y[i]); Dfs(1);printf("%d\n",ans); return 0;}
10.30 morning