18.4.09 模擬考 zhx P75
題目鏈接 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; } inlinevoid 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