1. 程式人生 > >18.4.09 模擬考 zhx P75

18.4.09 模擬考 zhx P75

image love oid 不能 格式 n! rand ios har

題目鏈接 https://files.cnblogs.com/files/lovewhy/P75.pdf

                                       P75
                              競賽時間: ??????????:??-??:??
技術分享圖片


註意事項(請務必仔細閱讀)

T1

【 問題描述】

從1 ? N中找一些數乘起來使得答案是一個完全平方數,求這個完全平方數
最大可能是多少。
【輸入格式】
第一行一個數字N。
【輸出格式】
一行一個整數代表答案對100000007取模之後的答案。
【樣例輸入】
7
【樣例輸出】
144
【樣例解釋】
但是塔外面有東西。
【數據規模與約定】
對於20%的數據, 1 ≤ N ≤ 100。
對於50%的數據, 1 ≤ N ≤ 5000。
對於70%的數據, 1 ≤ N ≤ 10^5。
對於100%的數據, 1 ≤ N ≤ 5 × 10^6。

//數學題2333
//竟然考了數學題mmp
//果然翻車了
//T1一分也沒有
//數論是個大坑,埋葬了我

//把n!分解質因數,記錄質因子出現的個數
//如果某個質因子a出現了偶數次,假設是b次,那麽它就可以由a^(b/2) * a^(b/2)得到,
//也就是說,只要這個質因子出現了偶數次,它就組成了一個完全平方數
//如果多個質因子出現了偶數次,同理,他們也可以都分成兩半再乘起來得到 
//如果是奇數呢?
//那就丟一個,使其變成偶數次 

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include
<algorithm> using namespace std; const int mod=1e8+7; const int N=5e6+5; int n; int tot[N]; int prime[N],cnt; bool nprime[N]; inline int read() { char c=getchar();int num=0; for(;!isdigit(c);c=getchar()); for(;isdigit(c);c=getchar()) num=num*10+c-0; return num; } inline
void init() { long long tmp; for(int i=2;i<=n;++i) { if(!nprime[i]) prime[++cnt]=i; for(int j=1;j<=cnt;++j) { tmp=1ll*prime[j]*i; if(tmp>n) break; nprime[tmp]=1; if(i%prime[j]==0) break; } } } long long ksm(long long a,long long k) { long long Ans=1; while(k) { if(k&1) Ans=Ans*a,Ans%=mod; k>>=1; a*=a; a%=mod; } return Ans; } inline void work() { for(int i=1;i<=cnt;++i) { int tmp=n; while(tmp) { tot[i]+=tmp/prime[i]; tmp/=prime[i]; } } } int main() { n=read(); init(); work(); long long ans=1; for(int i=1;i<=cnt;++i) { ans*=1ll*ksm(prime[i],tot[i]/2*2); ans%=mod; } printf("%lld",ans); return 0; }

T2

【問題描述】

有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。

技術分享圖片
//T2...
//想想。。。它什麽時候不如我們厲害呢? 
//就是平均值不在[l,r]唄。。。。
//,,....mmp
//沒點赫拉克勒斯。

//ei?突然發現T2兩秒時限

//不知道能不能n^2過30分 

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;

const int N=5e5+5;

int n,l,r;
int sum[N];
int fenmu,fenzi;

inline int read()
{
    char c=getchar();int num=0,f=1;
    for(;!isdigit(c);c=getchar())
        f=c==-?-1:f;
    for(;isdigit(c);c=getchar())
        num=num*10+c-0;
    return num*f;
}

int gcd(int x,int y)
{
    int tmp;
    while(y)
    {
        tmp=x;
        x=y;
        y=tmp%y;
    }
    return x;
}

int main()
{
    freopen("jian.in","r",stdin);
    freopen("jian.out","w",stdout);
    n=read(),l=read(),r=read();
    if(n<=10000)
    {
        for(int i=1,a;i<=n;++i)
        {
            a=read();
            sum[i]=sum[i-1]+a;
    //        cout<<sum[i]<<" ";
        }
    //    cout<<endl;
        fenmu=n*(n+1)>>1;
    //    cout<<"fenmu: "<<fenmu<<‘\n‘;
        int num,len;
        for(int i=1;i<=n;++i)
        {
            for(int j=i;j<=n;++j)
            {
                num=sum[j]-sum[i-1];
                len=j-i+1;
                if(num>=l*len&&num<=r*len)
                    ++fenzi;
            }
        }
        if(!fenzi)
            puts("0");
        else if(fenzi==fenmu)
            puts("1");
        else
        {
            int g=gcd(fenzi,fenmu);
            printf("%d/%d",fenzi/g,fenmu/g);
        }
    }
    else
        puts("0");
    fclose(stdin);
    fclose(stdout);
    return 0;
}
前綴和O(n^2) 30分

T3

【問題描述】
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。

暴力是沖著30分去的,但是竟然有50分2333

技術分享圖片
//顯然的是,如果是圍多棵蔥的話,那麽直接在外圍圍的長度==拐彎圍的長度
//給這些蔥按坐標排個序 

//長度等於((x0-x1+1)+(y0-y1+1))*2

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<ctime>
#define A lb[i].dax
#define B lb[i].xiaox
#define C lb[i].day
#define D lb[i].xiaoy
using std::min;
using std::max;
using std::sort;

const int N=1e3+5;
const int INF=0x7f7f7f7f;

int m,k,n;
struct LB
{
    int xiaox,xiaoy,dax,day;
}lb[20];
struct CONG
{
    int x,y;
}cong[N];

inline int read()
{
    char c=getchar();int num=0;
    for(;!isdigit(c);c=getchar());
    for(;isdigit(c);c=getchar())
        num=num*10+c-0;
    return num;
}

int a,b;
int Ans,tmp;
void dfs(int now)
{
    if(now==n+1)
    {
        tmp=0;
        for(int i=1;i<=k;++i)
        {
            if(A)
            {
                tmp+=((A-B+1)+(C-D+1))*2;
                if(tmp>=Ans)
                    return;
            }
        }
        Ans=min(Ans,tmp);
        return;
    }
    for(int i=1;i<=k;++i)
    {
        int a1=A,a2=B,a3=C,a4=D;
        A=max(A,cong[now].x);
        B=min(B,cong[now].x);
        C=max(C,cong[now].y);
        D=min(D,cong[now].y);
        dfs(now+1);
        A=a1,B=a2,C=a3,D=a4;
    }
}

int main()
{
    freopen("dan.in","r",stdin);
    freopen("dan.out","w",stdout);
    if((k<=5&&n<=10)||k==1||k==2)
    {
        m=read(),k=read(),n=read();
        for(int i=1;i<=n;++i)
            cong[i].x=read(),cong[i].y=read();
        Ans=INF;
        for(int i=1;i<=k;++i)
            B=D=INF;
        dfs(1);
        printf("%d",Ans);
    }
    else
    {
        srand(time(NULL));
        printf("%d",rand()%101+1);
    }
    fclose(stdin);
    fclose(stdout);
    return 0;
}
/*
1000 3 16
1 65
142 455
123 456
545 848
748 132
877 1000
746 712
416 745
786 136
456 452
413 748
13 11
45 485
132 748
412 44
32 453
1 1
*/

/*
1000 2 16
1 65
142 455
123 456
545 848
748 132
877 1000
746 712
416 745
786 136
456 452
413 748
13 11
45 485
132 748
412 44
32 453
1 1
*/
考場的50分暴力

只加卡時有60分,把if(now==n+1)裏的計算拿到外邊當了剪枝之後,可以達到95分了!!23333+1

但是在luogu上只能卡到80分。。。。

clock真好用!

技術分享圖片
//顯然的是,如果是圍多棵蔥的話,那麽直接在外圍圍的長度==拐彎圍的長度
//給這些蔥按坐標排個序 

//長度等於((x0-x1+1)+(y0-y1+1))*2

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<ctime>
#define A lb[i].dax
#define B lb[i].xiaox
#define C lb[i].day
#define D lb[i].xiaoy
using std::min;
using std::max;
using std::sort;

const int N=1e3+5;
const int INF=0x7f7f7f7f;

int m,k,n;
struct LB
{
    int xiaox,xiaoy,dax,day;
}lb[20];
struct CONG
{
    int x,y;
}cong[N];

inline int read()
{
    char c=getchar();int num=0;
    for(;!isdigit(c);c=getchar());
    for(;isdigit(c);c=getchar())
        num=num*10+c-0;
    return num;
}

int a,b;
int Ans,tmp;
void dfs(int now)
{
    if(clock()>19980)
    {
        printf("%d",Ans);
        exit(0);
    }
    tmp=0;
    for(int i=1;i<=k;++i)
    {
        if(A)
        {
            tmp+=((A-B+1)+(C-D+1))*2;
            if(tmp>=Ans)
                return;
        }
    }
    if(now==n+1)
    {
        Ans=tmp;
        return;
    }
    for(int i=1;i<=k;++i)
    {
        int a1=A,a2=B,a3=C,a4=D;
        A=max(A,cong[now].x);
        B=min(B,cong[now].x);
        C=max(C,cong[now].y);
        D=min(D,cong[now].y);
        dfs(now+1);
        A=a1,B=a2,C=a3,D=a4;
    }
}

int main()
{
//    freopen("dan.in","r",stdin);
//    freopen("dan.out","w",stdout);
    if((k<=5&&n<=10)||k==1||k==2)
    {
        m=read(),k=read(),n=read();
        for(int i=1;i<=n;++i)
            cong[i].x=read(),cong[i].y=read();
        Ans=INF;
        for(int i=1;i<=k;++i)
            B=D=INF;
        dfs(1);
        printf("%d",Ans);
    }
    else
    {
        srand(time(NULL));
        printf("%d",rand()%101+1);
    }
    fclose(stdin);
    fclose(stdout);
    return 0;
}
/*
1000 3 16
1 65
142 455
123 456
545 848
748 132
877 1000
746 712
416 745
786 136
456 452
413 748
13 11
45 485
132 748
412 44
32 453
1 1
*/

/*
1000 2 16
1 65
142 455
123 456
545 848
748 132
877 1000
746 712
416 745
786 136
456 452
413 748
13 11
45 485
132 748
412 44
32 453
1 1
*/
加了卡時+剪枝的95分暴力

18.4.09 模擬考 zhx P75