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 long
using 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;
}
View Code

 

【问题描述】

有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 500010
using 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;
}
View Code

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 500010
using 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;
}
View Code

 

【问题描述】
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 1e9
using 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;
}
View Code

 

posted @ 2016-11-07 09:06  一入OI深似海  阅读(170)  评论(0编辑  收藏  举报