【问题描述】
从中找一些数乘起来使得答案是一个完全平方数,求这个完全平方数最大可能是多少。
【输入格式】
第一行一个数字。
【输出格式】
一行一个整数代表答案对取模之后的答案。
【样例输入】
7
【样例输出】
144
【样例解释】
但是塔外面有东西。
【数据规模与约定】
对于20%的数据,1<=N<=100。
对于50%的数据,1<=N<=5000。
对于70%的数据,1<=N<=10^5。
对于100%的数据,1<=N<=5*10^6。
题解:可以将n的阶乘质因数分解,然后若质因数的指数为奇数则指数减1乘进答案。若为偶数直接乘进答案。因为只有当质因数的指数是偶数时,才能开方开出来,当质因数指数是奇数时,可以除以一个这个质因数,就可以开出来了。
#include<cstdio> #include<iostream> #include<cstring> #include<algorithm> #define N 5000100 using namespace std; const int M=100000007; int n,num(0); long long ans(1); int ss[N],zs[N]={0}; bool f[N]={0}; int oula()//欧拉筛法 { for (int i=2;i<=n;i++) { if (!f[i]) ss[++num]=i; for (int j=1;j<=num,ss[j]*i<=n;j++) { f[ss[j]*i]=1; if (!(i%ss[j])) break; } } } long long jc(long long p,long long k)//快速幂 { long long ki=1; while (k) { if (k%2) ki=ki*p%M; p=p*p%M; k/=2; } return ki; } int main() { freopen("hao.in","r",stdin); freopen("hao.out","w",stdout); scanf("%d",&n); oula(); for (int i=1;i<=num;i++)//n的阶乘质因数分解 { int k=n; while (k) { zs[i]+=k/ss[i]; k/=ss[i]; } } for (int i=1;i<=num;i++) { if (zs[i]%2) ans=ans*jc(ss[i],zs[i]-1)%M; else ans=ans*jc(ss[i],zs[i])%M; } cout<<ans<<endl; fclose(stdin); fclose(stdout); return 0; }
【问题描述】
有个数,随机选择一段区间,如果这段区间的所有数的平均值在中则你比较厉害。求你比较厉害的概率。
【输入格式】
第一行有三个数,含义如上描述。
接下来一行有个数代表每一个数的值。
【输出格式】
输出一行一个分数代表答案,其中互质。如果答案为整数则直接输出该整数即可。
【样例输入1】
4 2 3
3 1 2 4
【样例输出1】
7/10
【样例输入2】
4 1 4
3 1 2 4
【样例输出2】
1
【样例解释】
塔外面有棵树。
【数据规模与约定】
对于30%的数据,1<=N<=10^4。
对于60%的数据,1<=N<=10^5。
对于100%的数据,1<=N<=5*10^5,0<l<=r<=100.
题解:可以先求出平均值小于l的区间的个数与平均值大于r的区间的个数和,然后用总的区间总数减去不满足条件的区间数就是满足的区间总数。
求平均值小于l的区间个数时,可以先求出a[i]-l的前缀和li[i],那么此时小于0的区间即为小于l的区间。由于区间a[i]~a[j]的值是li[j]-li[i-1],要想满足区间小于0,则li[i-1]>li[j],那么这就是求li数组的逆序对数。要注意加上单独一个数<0的情况。
求平均值大于r的区间个数时类似,但是求得是r-a[i]的前缀和。
#include<cstdio> #include<iostream> #include<cstring> #include<algorithm> #include<ctime> #define N 500100 #define ll long long using namespace std; ll n,l,r,ans(0),fz,fm; //注意开long long ,不然会爆掉 ll l1[N]={0},b[N]={0},a[N]={0}; ll gcd(ll x,ll y) { if (y==0) return x; else return gcd(y,x%y); } void xx() { memset(b,0,sizeof(b)); memset(l1,0,sizeof(l1)); ans=0; } void msort(ll x,ll y) { if (x>=y) return ; ll mid=(x+y)>>1; msort(x,mid); msort(mid+1,y); ll i=x,j=mid+1,t=x-1; while (i<=mid&&j<=y) { if (l1[i]<=l1[j]) b[++t]=l1[i++]; else { ans+=mid-i+1; b[++t]=l1[j++]; } } while (i<=mid) b[++t]=l1[i++]; while (j<=y) b[++t]=l1[j++]; for (i=x;i<=y;i++) l1[i]=b[i]; return ; } int main() { freopen("jian.in","r",stdin); freopen("jian.out","w",stdout); cin>>n>>l>>r; for (ll i=1;i<=n;i++) scanf("%lld",&a[i]); for (ll i=1;i<=n;i++) l1[i]=l1[i-1]+a[i]-l; for (ll i=1;i<=n;i++)//不要忘记判断单独一个数。- -找了好长好长时间错误。 if (l1[i]<0) ans++; msort(1,n); fz=ans; xx(); for (ll i=1;i<=n;i++) l1[i]=l1[i-1]+r-a[i]; for (ll i=1;i<=n;i++) if (l1[i]<0) ans++; msort(1,n); fz+=ans; fm=(n*(n+1)/2); //所有的组合方式 fz=fm-fz; if (fz==0) printf("0 "); else if (fz==fm) { printf("1 "); } else { ll ki=gcd(fz,fm); fz/=ki; fm/=ki; cout<<fz<<'/'; cout<<fm; } fclose(stdin); fclose(stdout); return 0; }
【问题描述】
的方阵上有棵葱,你要修一些栅栏把它们围起来。一个栅栏是一段沿着网格建造的封闭图形(即要围成一圈)。各个栅栏之间应该不相交、不重叠且互相不包含。如果你最多修个栅栏,那么所有栅栏的长度之和最小是多少?
【输入格式】
第一行三个整数。
接下来行每行两个整数代表某棵葱的位置。
【输出格式】
一行一个整数代表答案。
【样例输入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。
题解:暴力搜索。有25分会超时,此时用zhx教的方法,用clock()函数判断一下运行时间,超过一定时间直接输出答案,停止搜索。可以骗取20分。
#include<cstdio> #include<iostream> #include<cstring> #include<ctime> #include<algorithm> #define N 20 #define ll long long using namespace std; int m,k,n,ans=0x7fffffff/3; int x1[N],x2[N],y1[N],y2[N]; int x[N],y[N]; void xx() { memset(x1,127/3,sizeof(x1)); memset(y1,127/3,sizeof(y1)); } void dfs(int now)//枚举每跟葱 { if (clock()>1950) //超过时间限制,直接输出 { printf("%d ",ans); exit(0); } int mx=0; for (int i=1;i<=k;i++) { if (x1[i]==x1[0]) continue; mx+=(x2[i]-x1[i]+1+y2[i]-y1[i]+1)*2; } if (mx>=ans) return ; if (now==n+1) { int mx=0; for (int i=1;i<=k;i++) { if (x1[i]==x1[0]) continue; mx+=(x2[i]-x1[i]+1+y2[i]-y1[i]+1)*2; } ans=min(ans,mx); return ; } for (int i=1;i<=k;i++) { int a=x1[i],b=x2[i],c=y1[i],d=y2[i]; x1[i]=min(x1[i],x[now]); x2[i]=max(x2[i],x[now]); y1[i]=min(y1[i],y[now]); y2[i]=max(y2[i],y[now]); dfs(now+1); x1[i]=a;x2[i]=b;y1[i]=c;y2[i]=d; } } int main() { freopen("dan.in","r",stdin); freopen("dan.out","w",stdout); xx(); scanf("%d%d%d",&m,&k,&n); for (int i=1;i<=n;i++) scanf("%d%d",&x[i],&y[i]); dfs(1); printf("%d ",ans); fclose(stdin); fclose(stdout); return 0; }