10.3 广州集训 Day2
T1
1 數(shù)學(xué)課
程序文件名: number.c/cpp/pas
輸入文件: number.in
輸出文件: number.out
時(shí)間限制: 1s
空間限制: 256Mb
題目描述
數(shù)學(xué)課上,老師在黑板上寫了n個(gè)數(shù),然后讓大家做一個(gè)游戲:每次擦掉黑板上的兩個(gè)數(shù),然后在黑板上寫下這兩個(gè)數(shù)的乘積加一,直到最后只有一個(gè)數(shù)。同學(xué)們做了幾次這個(gè)游戲之后,發(fā)現(xiàn)最終剩下的數(shù)大小不一。同學(xué)們十分好奇,但老師說:“如果你們能保證剩下的數(shù)比我玩的時(shí)候剩下的數(shù)要小或者相等,那我就告訴你們?cè)颉!蓖瑢W(xué)們現(xiàn)在十分想知道原因,你能幫幫他們嗎?
輸入格式
第一行有一個(gè)正整數(shù)n,代表數(shù)字的個(gè)數(shù)。
下一行有n個(gè)正整數(shù)a1; a2; :::; an,表示老師在黑板上寫下的數(shù)。
輸出格式
一個(gè)數(shù),表示同學(xué)們最后應(yīng)該剩下的數(shù)。對(duì)109 + 7取模。
樣例
輸入 ? ? ? ? ? ? ? ? ? ? ? ? ? ?輸出
3 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 15
2 2 3
樣例解釋:先將2和3擦掉,寫下7,再將7和2擦掉,寫下15。
數(shù)據(jù)范圍
對(duì)于20%的數(shù)據(jù),n≤8 ?,??≤10
對(duì)于40%的數(shù)據(jù),n≤8 ?
對(duì)于100%的數(shù)據(jù),n≤200 ?,??≤10^9
?
Solution:
簡(jiǎn)單模擬+貪心。
我們可以證明每次去兩個(gè)最大的數(shù)相乘一定比其余做法優(yōu)。
可以通過二叉樹說明。
假設(shè)a為左圖最小值,則左圖->右圖可以發(fā)現(xiàn)右圖更小。
進(jìn)行類似操作,可以發(fā)現(xiàn)最小值通過被替換一直會(huì)留在二叉樹中,而最大值則會(huì)被擦去。
也就是說,最小值總是最后擦去,而最大值被不斷刪除。
以此類推,每次的做法就是取兩個(gè)最大值相乘。
該做法是O(nlogn)。
1 #include<cstdio> 2 #include<algorithm> 3 #define MODE 1000000007 4 #define MAXN 205 5 #define ll long long 6 using namespace std; 7 int a[MAXN]; 8 int n; 9 ll ans=0; 10 inline int read(){ 11 int x=0,f=1;char ch=getchar(); 12 while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} 13 while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} 14 return x*f; 15 } 16 bool cmp(int x,int y){return x>y;} 17 int main(){ 18 freopen("number.in","r",stdin); 19 freopen("number.out","w",stdout); 20 n=read(); 21 for(int i=1;i<=n;i++) a[i]=read(); 22 sort(a+1,a+n+1,cmp); 23 //for(int i=1;i<=n;i++) printf("a[i]=%d\n",a[i]); 24 ans=a[1]; 25 for(int i=2;i<=n;i++){ 26 ans*=a[i];ans+=1;ans%=MODE; 27 } 28 printf("%d",ans); 29 return 0; 30 }T2
?
遺傳病(disease,2s,256M)
【題目描述】
眾所周知,近親結(jié)婚的后代患遺傳病的概率會(huì)大大增加。如果某一基因按常染色體隱性遺傳方式,其子女就可能因?yàn)槭峭蛔兗兒献佣l(fā)病。因此,近親婚配增加了某些常染色體隱性遺傳疾病的發(fā)生風(fēng)險(xiǎn)。
現(xiàn)在有n個(gè)人,每個(gè)人都有一個(gè)遺傳特征值a_i,假設(shè)第i個(gè)人和j個(gè)人結(jié)婚,那么風(fēng)險(xiǎn)系數(shù)為gcd?(a_i,a_j),法律規(guī)定只有風(fēng)險(xiǎn)系數(shù)為1時(shí)兩個(gè)人才能結(jié)婚。
F同學(xué)開了一個(gè)婚姻介紹所,這n個(gè)人可能會(huì)來登記,當(dāng)然也有可能登記后取消,也有可能取消后再登記。F同學(xué)的任務(wù)就是,求出當(dāng)前所有登記的人中,有多少對(duì)人是可以結(jié)婚的。
剛開始所有人都沒有登記。
為出題需要,不考慮性別,基因突變和染色體變異等QAQ。
【輸入格式】
從disease.in中讀入。
第一行兩個(gè)整數(shù)n和q,n表示人數(shù),q表示登記和登出的總次數(shù)。
第二行n個(gè)整數(shù)a_1,a_2,…,a_n,意義如上所述。
接下來q行,每行一個(gè)整數(shù)x。如果當(dāng)前第x個(gè)人沒有登記,那么第x個(gè)人登記;如果當(dāng)前第x個(gè)人已經(jīng)登記了,那么其取消登記。
【輸出格式】
輸出到disease.out中。
一共q行,第i行表示第i個(gè)操作后,當(dāng)前所有登記的人中有多少對(duì)人是可以結(jié)婚的。
【樣例一輸入】
5 6
1 2 3 4 6
1
2
3
4
5
1
【樣例一輸出】
0
1
3
5
6
2
【子任務(wù)】
30%數(shù)據(jù),1<=n,q<=1000
100%數(shù)據(jù),1<=n,q<=100000,1<=ai<=500000
Solution:
本題考察容斥原理。
30%數(shù)據(jù),每加入或刪除一個(gè)數(shù),掃一下已經(jīng)登記的人求一下gcd即可,時(shí)間復(fù)雜度O(n^2)
100%數(shù)據(jù),考慮容斥原理。
比如加入一個(gè)數(shù)30,那么60的質(zhì)因數(shù)集合為{2,3,5}(重復(fù)的去掉)
兩個(gè)數(shù)互質(zhì)等價(jià)于質(zhì)因數(shù)集合交集問空集。
記|S|為當(dāng)且已登記的人中質(zhì)因數(shù)集合的子集有S的人數(shù),其中S是一個(gè)質(zhì)因數(shù)集合
特別地,記|{1}|=當(dāng)前已登記的人數(shù)
與30互質(zhì)的個(gè)數(shù)=|{1}|-|{2}|-|{3}|-|{5}|+|{2,3}|+|{2,5}|+|{3,5}|-|{2,3,5}|
因?yàn)?*3*5*7*11*13*17=510510>500000,所以每個(gè)數(shù)最多只有6個(gè)質(zhì)因數(shù)(重復(fù)的去掉)
2^6=64,時(shí)間復(fù)雜度為O(64n)。
Other:
還沒有A。
本題也是莫比烏斯反演。
1 //std 2 #include<cstdio> 3 #include<cstdlib> 4 #include<cassert> 5 #include<iostream> 6 #include<fstream> 7 #include<algorithm> 8 #include<cstring> 9 #include<string> 10 #include<cmath> 11 #include<queue> 12 #include<stack> 13 #include<map> 14 #include<utility> 15 #include<set> 16 #include<bitset> 17 #include<vector> 18 #include<functional> 19 #include<deque> 20 #include<cctype> 21 #include<climits> 22 #include<complex> 23 #include<bits/stdc++.h> 24 #include<ctime> 25 #include<ext/rope> 26 27 using namespace __gnu_cxx; 28 using namespace std; 29 30 typedef long long LL; 31 typedef double DB; 32 typedef pair<int,int> PII; 33 typedef pair<DB,DB> PDD; 34 typedef complex<DB> CP; 35 typedef vector<int> VI; 36 37 #define mmst(a,v) memset(a,v,sizeof(a)) 38 #define mmcy(a,b) memcpy(a,b,sizeof(a)) 39 #define fill(a,l,r,v) fill(a+l,a+r+1,v) 40 #define re(i,a,b) for(i=(a);i<=(b);i++) 41 #define red(i,a,b) for(i=(a);i>=(b);i--) 42 #define fi first 43 #define se second 44 #define mp(a,b) make_pair(a,b) 45 #define pb(a) push_back(a) 46 #define two(k) (1<<(k)) 47 #define SZ(x) (int(x.size())) 48 #define all(x) (x).begin(),(x).end() 49 #define ire(i,v,x) for(i=0,v=i<SZ(x)?x[i]:0;i<SZ(x);v=x[++i]) 50 #define ls (rt<<1) 51 #define rs (rt<<1|1) 52 #define MID ((l+r)>>1) 53 54 template<class T>inline T sqr(T x){return x*x;} 55 template<class T>inline void upmin(T &t,T tmp){if(t>tmp)t=tmp;} 56 template<class T>inline void upmax(T &t,T tmp){if(t<tmp)t=tmp;} 57 58 inline int sgn(DB x){if(abs(x)<1e-9)return 0;return(x>0)?1:-1;} 59 const DB Pi=acos(-1.0); 60 61 //void enlargestack(){int size=256<<10;char *p=(char*)malloc(size)+size;__asm__("movl %0, %%esp\n"::"r"(p));} 62 63 int gint() 64 { 65 int res=0;bool neg=0;char z; 66 for(z=getchar();z!=EOF && z!='-' && !isdigit(z);z=getchar()); 67 if(z==EOF)return 0; 68 if(z=='-'){neg=1;z=getchar();} 69 for(;z!=EOF && isdigit(z);res=(res<<3)+(res<<1)+z-'0',z=getchar()); 70 return (neg)?-res:res; 71 } 72 LL gll() 73 { 74 LL res=0;bool neg=0;char z; 75 for(z=getchar();z!=EOF && z!='-' && !isdigit(z);z=getchar()); 76 if(z==EOF)return 0; 77 if(z=='-'){neg=1;z=getchar();} 78 for(;z!=EOF && isdigit(z);res=res*10+z-'0',z=getchar()); 79 return (neg)?-res:res; 80 } 81 82 const int maxn=210000; 83 const int maxm=510000; 84 85 int n,q,m; 86 int a[maxn]; 87 int cnt,flag[maxm],prime[maxm],p[maxm]; 88 vector<int> b[maxn]; 89 int in[maxn]; 90 int table[maxm]; 91 LL res; 92 93 void init() 94 { 95 int i,j; 96 re(i,2,m) 97 { 98 if(!flag[i])prime[++cnt]=i; 99 for(j=1;j<=cnt && i*prime[j]<=m;j++) 100 { 101 flag[i*prime[j]]=1; 102 p[i*prime[j]]=prime[j]; 103 if(i%prime[j]==0)break; 104 } 105 } 106 re(i,1,n) 107 { 108 int x=a[i]; 109 while(x!=1) 110 { 111 int t=flag[x]?p[x]:x; 112 b[i].pb(t); 113 while(x%t==0)x/=t; 114 } 115 } 116 } 117 118 void dfs(int x,int k,int mult,int f) 119 { 120 if(k==SZ(b[x])) 121 { 122 res+=in[x]==1?table[mult]*in[x]*f:(table[mult]-1)*in[x]*f; 123 table[mult]+=in[x]; 124 return; 125 } 126 dfs(x,k+1,mult*b[x][k],-f); 127 dfs(x,k+1,mult,f); 128 } 129 130 int main() 131 { 132 freopen("disease.in","r",stdin); 133 freopen("disease.out","w",stdout); 134 int i; 135 n=gint();q=gint(); 136 re(i,1,n)a[i]=gint(),upmax(m,a[i]); 137 init(); 138 fill(in,1,n,1); 139 while(q--) 140 { 141 int x=gint(); 142 dfs(x,0,1,1); 143 in[x]=-in[x]; 144 printf("%I64d\n",res); 145 } 146 return 0; 147 }
?
T3
瓜分領(lǐng)土(2s,512MB)
?????? 石頭、剪刀和布鬧別扭了,他們要分家。
?????? 他們生活在一個(gè)離散的一維空間里,簡(jiǎn)單點(diǎn)說,他們擁有在一條直線上的N間房子,每間房子有一個(gè)風(fēng)水值(有正有負(fù))。
?????? 然后,他們決定將這N間房子分成非空的三個(gè)連續(xù)段,從左到右數(shù),第一段的房子全部屬于石頭,第二段的房子全部屬于剪刀,第三段的房子全部屬于布。
?????? 由于他們希望公平,并且又由于剪刀是他們的老大哥,他們決定根據(jù)這些條件制定了一個(gè)評(píng)判標(biāo)準(zhǔn):
?????? 設(shè)石頭擁有的房子的風(fēng)水值和為a,剪刀擁有的房子的風(fēng)水值和為b,布擁有的房子的風(fēng)水值和為c,剪刀擁有n間房子。
?????? 那么通過給定一個(gè)參數(shù)x。
?????? 那么,這種分配的合理值就是max(a,b,c)-min(a,b,c)+x*n.
?????? 合理值越小,表示這種分配越合理。
?????? 因此,我們現(xiàn)在就是要求出這個(gè)最小的合理值。
?
輸入格式
?????? 第一行一個(gè)正整數(shù)N。
?????? 第二行有N個(gè)整數(shù),表示房子的風(fēng)水值,按從左到右的順序給出。
?????? 第三行一個(gè)整數(shù)x。
?
輸出格式
?????? 一行一個(gè)整數(shù),表示最小的合理值。
?
輸入樣例:
?????? 4
?????? 1 1 1 1
?????? -1
?
輸出樣例:
?????? -1
?
數(shù)據(jù)范圍:
?????? 對(duì)于30%的數(shù)據(jù),N<=10.
?????? 對(duì)于70%的數(shù)據(jù),N<=1000.
?????? 對(duì)于100%的數(shù)據(jù),N<=100000,保證所有運(yùn)算結(jié)果在long long范圍內(nèi)。
?
Solution:
線段樹+二分+離散+枚舉+數(shù)學(xué)結(jié)論。
//留坑。以及正解寫掛60<暴力O(n^2)的慘案。
?
Other:
根據(jù)三段的和a,b,c的大小關(guān)系,分成6種情況討論。對(duì)于每種情況,根據(jù)計(jì)算出來的答的式子,利用數(shù)據(jù)結(jié)構(gòu)求區(qū)間最值,從而解決這道題。
這就是官方題解了(顯然是假的對(duì)不對(duì)),具體的要過一段時(shí)間放上來了。
//在code中加入了一些注釋 希望可以懂惹
1 #include<bits/stdc++.h> 2 using namespace std; 3 4 const int maxn=100000+15; 5 const long long oo=1ll << 60; 6 int n,a[maxn]; 7 long long sum[maxn],x; 8 long long que[maxn]; 9 int all; 10 long long tree[4*maxn]; 11 int foundr(long long x) 12 { 13 int l=0,r=all+1,midd; 14 while (l+1<r) 15 { 16 midd=(l+r)>>1; 17 if (que[midd]<=x) l=midd; 18 else r=midd; 19 } 20 return l; 21 } 22 int foundl(long long x) 23 { 24 int l=0,r=all+1,midd; 25 while (l+1<r) 26 { 27 midd=(l+r)>>1; 28 if (que[midd]>=x) r=midd; 29 else l=midd; 30 } 31 return r; 32 } 33 int ins(int root,int l,int r,int x,long long y) 34 { 35 if (r<x || l>x) return 0; 36 tree[root]=min(tree[root],y); 37 if (l==r) return 0; 38 int mid=(l+r)>>1; 39 ins(root<<1,l,mid,x,y); 40 ins(root<<1|1,mid+1,r,x,y); 41 return 0; 42 } 43 long long found(int rot,int l,int r,int x,int y) 44 { 45 if (l>y || r<x) return oo; 46 if (x<=l && r<=y) return tree[rot]; 47 int mid=(l+r)>>1; 48 return min(found(rot<<1,l,mid,x,y),found(rot<<1|1,mid+1,r,x,y)); 49 } 50 long long work1() 51 { 52 for (int i=1;i<=4*all;i++) tree[i]=oo; 53 long long ans=oo; 54 for (int i=n-2;i>=1;i--) 55 { 56 int u=foundr(sum[i+1]); 57 ins(1,1,all,u,-sum[i+1]+x*(i+1)); 58 int l=foundl(2*sum[i]),r=foundr((sum[n]+sum[i])/2); 59 if (l>r) continue; 60 ans=min(ans,sum[n]-sum[i]-x*i+found(1,1,all,l,r)); 61 } 62 return ans; 63 } 64 long long work2() 65 { 66 for (int i=1;i<=4*all;i++) tree[i]=oo; 67 long long ans=oo; 68 for (int i=n-2;i>=1;i--) //這里我們采用的是枚舉i,然后看所有j>i的合法情況中的最優(yōu)解 69 { 70 int u=foundr(sum[i+1]); 71 ins(1,1,all,u,sum[i+1]+x*(i+1)); //準(zhǔn)備開始枚舉i,所以把j=i+1的情況加進(jìn)線段樹里面 72 int l=foundl((sum[n]+sum[i]+1)/2),r=foundr(sum[n]-sum[i]); //確定sum[j]的范圍 73 if (l>r) continue; 74 ans=min(ans,-2*sum[i]-x*i+found(1,1,all,l,r)); //求解sum[j]在某范圍內(nèi)的最優(yōu)值 75 } 76 return ans; 77 } 78 long long work3() 79 { 80 for (int i=1;i<=4*all;i++) tree[i]=oo; 81 long long ans=oo; 82 for (int i=n-2;i>=1;i--) 83 { 84 int u=foundr(sum[i+1]); 85 ins(1,1,all,u,-2*sum[i+1]+x*(i+1)); 86 int l=1,r=foundr(min(sum[n]-sum[i],2*sum[i])); 87 if (l>r) continue; 88 ans=min(ans,sum[n]+sum[i]-x*i+found(1,1,all,l,r)); 89 } 90 return ans; 91 } 92 long long work4() 93 { 94 for (int i=1;i<=4*all;i++) tree[i]=oo; 95 long long ans=oo; 96 for (int i=n-2;i>=1;i--) 97 { 98 int u=foundr(sum[i+1]); 99 ins(1,1,all,u,-sum[i+1]+x*(i+1)); 100 int l=foundl(sum[n]-sum[i]),r=foundr((sum[n]+sum[i])/2); 101 if (l>r) continue; 102 ans=min(ans,2*sum[i]-x*i+found(1,1,all,l,r)); 103 } 104 return ans; 105 } 106 long long work5() 107 { 108 for (int i=1;i<=4*all;i++) tree[i]=oo; 109 long long ans=oo; 110 for (int i=n-2;i>=1;i--) 111 { 112 int u=foundr(sum[i+1]); 113 ins(1,1,all,u,2*sum[i+1]+x*(i+1)); 114 int l=foundl(max(2*sum[i],sum[n]-sum[i])),r=all; 115 if (l>r) continue; 116 ans=min(ans,-sum[i]-sum[n]-x*i+found(1,1,all,l,r)); 117 } 118 return ans; 119 } 120 long long work6() 121 { 122 for (int i=1;i<=4*all;i++) tree[i]=oo; 123 long long ans=oo; 124 for (int i=n-2;i>=1;i--) 125 { 126 int u=foundr(sum[i+1]); 127 ins(1,1,all,u,sum[i+1]+x*(i+1)); 128 int l=foundl((sum[i]+sum[n]+1)/2),r=foundr(2*sum[i]); 129 if (l>r) continue; 130 ans=min(ans,sum[i]-sum[n]-x*i+found(1,1,all,l,r)); 131 } 132 return ans; 133 } 134 int main() 135 { 136 freopen("B.in","r",stdin); 137 freopen("B.out","w",stdout); 138 scanf("%d",&n); 139 for (int i=1;i<=n;i++) scanf("%d",&a[i]); 140 cin >> x; 141 for (int i=1;i<=n;i++) sum[i]=sum[i-1]+a[i]; 142 for (int i=2;i<n;i++) que[++all]=sum[i]; 143 sort(que+1,que+all+1); 144 all=unique(que+1,que+all+1)-que-1; 145 long long ans=oo; 146 ans=min(ans,work1()); //a<=b<=c 147 ans=min(ans,work2()); //a<=c<=b 148 ans=min(ans,work3()); //b<=a<=c 149 ans=min(ans,work4()); //b<=c<=a 150 ans=min(ans,work5()); //c<=a<=b 151 ans=min(ans,work6()); //c<=b<=a 152 //不排除分類標(biāo)準(zhǔn)有誤 153 cout << ans << endl; 154 return 0; 155 }?
轉(zhuǎn)載于:https://www.cnblogs.com/drizzly/p/7623971.html
總結(jié)
以上是生活随笔為你收集整理的10.3 广州集训 Day2的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 巧用云计算 突围移动APP行业乱象
- 下一篇: 43. ExtJs控件属性配置详细