浙江理工大学2019年5月赛
Problem A?24點(diǎn)
比賽地址:http://47.96.116.66/problem.php?cid=1275&pid=0
補(bǔ)題地址:http://47.96.116.66/problem.php?id=2110
題意:
題解:
按題意模擬即可
用next_permutation()枚舉數(shù)字的所有排列情況
對(duì)于某種排列,用四進(jìn)制枚舉出運(yùn)算符的所有情況
最后再枚舉括號(hào)的情況
C++版本一
/* *@Author: STZG *@Language: C++ */ #include <bits/stdc++.h> #include<iostream> #include<algorithm> #include<cstdlib> #include<cstring> #include<cstdio> #include<string> #include<vector> #include<bitset> #include<queue> #include<deque> #include<stack> #include<cmath> #include<list> #include<map> #include<set> //#define DEBUG #define RI register int #define endl "\n" using namespace std; typedef long long ll; //typedef __int128 lll; const int N=100000+10; const int M=100000+10; const int MOD=1e9+7; const double PI = acos(-1.0); const double EXP = 1E-8; const int INF = 0x3f3f3f3f; int t,n,m,k,p,l,r,u,v; int ans,cnt,flag,temp,sum; int a[5]; char str; struct node{}; bool check(){int A=a[1];int B=a[2];int C=a[3];int D=a[4];if(A+B+C+D==24)return 1;if(A+B+C-D==24)return 1;if(A+B+C*D==24)return 1;if(A+(B+C)*D==24)return 1;if((A+B+C)*D==24)return 1;if(A+B+C/D==24&&1.0*C/D==C/D)return 1;if(A+(B+C)/D==24&&1.0*(B+C)/D==(B+C)/D)return 1;if((A+B+C)/D==24&&1.0*(A+B+C)/D==(A+B+C)/D)return 1;if(A+B-C+D==24)return 1;if(A+B-C-D==24)return 1;if(A+B-C*D==24)return 1;if(A+(B-C)*D==24)return 1;if((A+B-C)*D==24)return 1;if(A+B-C/D==24&&1.0*C/D==C/D)return 1;if(A+(B-C)/D==24&&1.0*(B-C)/D==(B-C)/D)return 1;if((A+B-C)/D==24&&1.0*(A+B-C)/D==(A+B-C)/D)return 1;if(A+B*C+D==24)return 1;if((A+B)*C+D==24)return 1;if(A+B*(C+D)==24)return 1;if((A+B)*(C+D)==24)return 1;if(A+B*C-D==24)return 1;if((A+B)*C-D==24)return 1;if(A+B*(C-D)==24)return 1;if((A+B)*(C-D)==24)return 1;if(A+B*C*D==24)return 1;if((A+B)*C*D==24)return 1;if(A+B*C/D==24&&1.0*B*C/D==B*C/D)return 1;if((A+B)*C/D==24&&1.0*(A+B)*C/D==(A+B)*C/D)return 1;if((A+B*C)/D==24&&1.0*(A+B*C)/D==(A+B*C)/D)return 1;if(A+B/C+D==24&&1.0*B/C==B/C)return 1;if((A+B)/C+D==24&&1.0*(A+B)/C==(A+B)/C)return 1;if(A+B/(C+D)==24&&1.0*B/(C+D)==B/(C+D))return 1;if((A+B)/(C+D)==24&&1.0*(A+B)/(C+D)==(A+B)/(C+D))return 1;if(A+B/C-D==24&&1.0*B/C==B/C)return 1;if((A+B)/C-D==24&&1.0*(A+B)/C==(A+B)/C)return 1;if(C-D!=0&&A+B/(C-D)==24&&1.0*B/(C-D)==B/(C-D))return 1;if(C-D!=0&&(A+B)/(C-D)==24&&1.0*(A+B)/(C-D)==(A+B)/(C-D))return 1;if(A+B/C*D==24&&1.0*B/C*D==B/C*D)return 1;if((A+B)/C*D==24&&1.0*(A+B)/C*D==(A+B)/C*D)return 1;if(A+B/C/D==24&&1.0*B/C/D==B/C/D)return 1;if((A+B)/C/D==24&&1.0*(A+B)/C/D==(A+B)/C/D)return 1;if(A-B+C+D==24)return 1;if(A-B+C-D==24)return 1;if(A-B+C*D==24)return 1;if(A-(B+C)*D==24)return 1;if((A-B+C)*D==24)return 1;if(A-B+C/D==24&&1.0*C/D==C/D)return 1;if(A-(B+C)/D==24&&1.0*(B+C)/D==(B+C)/D)return 1;if((A-B+C)/D==24&&1.0*(A-B+C)/D==(A-B+C)/D)return 1;if(A-B-C+D==24)return 1;if(A-B-C-D==24)return 1;if(A-B-C*D==24)return 1;if(A-(B-C)*D==24)return 1;if((A-B-C)*D==24)return 1;if(A-B-C/D==24&&1.0*C/D==C/D)return 1;if(A-(B-C)/D==24&&1.0*(B-C)/D==(B-C)/D)return 1;if((A-B-C)/D==24&&1.0*(A-B-C)/D==(A-B-C)/D)return 1;if(A-B*C+D==24)return 1;if((A-B)*C+D==24)return 1;if(A-B*(C+D)==24)return 1;if((A-B)*(C+D)==24)return 1;if(A-B*C-D==24)return 1;if((A-B)*C-D==24)return 1;if(A-B*(C-D)==24)return 1;if((A-B)*(C-D)==24)return 1;if(A-B*C*D==24)return 1;if((A-B)*C*D==24)return 1;if(A-B*C/D==24&&1.0*C/D==C/D)return 1;if((A-B)*C/D==24&&1.0*(A-B)*C/D==(A-B)*C/D)return 1;if((A-B*C)/D==24&&1.0*(A-B*C)/D==(A-B*C)/D)return 1;if(A-B/C+D==24&&1.0*B/C==B/C)return 1;if((A-B)/C+D==24&&1.0*(A-B)/C==(A-B)/C)return 1;if(A-B/(C+D)==24&&1.0*B/(C+D)==B/(C+D))return 1;if((A-B)/(C+D)==24&&1.0*(A-B)/(C+D)==(A-B)/(C+D))return 1;if(A-B/C-D==24&&1.0*B/C==B/C)return 1;if((A-B)/C-D==24&&1.0*(A-B)/C==(A-B)/C)return 1;if(C-D!=0&&A-B/(C-D)==24&&1.0*B/(C-D)==B/(C-D))return 1;if(C-D!=0&&(A-B)/(C-D)==24&&1.0*(A-B)/(C-D)==(A-B)/(C-D))return 1;if(A-B/C*D==24&&1.0*B/C*D==B/C*D)return 1;if((A-B)/C*D==24&&1.0*(A-B)/C*D==(A-B)/C*D)return 1;if(A-B/C/D==24&&1.0*B/C/D==B/C/D)return 1;if((A-B)/C*D==24&&1.0*(A-B)/C*D==(A-B)/C*D)return 1;if(A*B+C+D==24)return 1;if(A*(B+C)+D==24)return 1;if(A*(B+C+D)==24)return 1;if(A*B+C-D==24)return 1;if(A*(B+C)-D==24)return 1;if(A*(B+C-D)==24)return 1;if(A*B+C*D==24)return 1;if(A*(B+C)*D==24)return 1;if(A*(B+C*D)==24)return 1;if((A*B+C)*D==24)return 1;if(A*B+C/D==24&&1.0*C/D==C/D)return 1;if(A*(B+C)/D==24&&1.0*A*(B+C)/D==A*(B+C)/D)return 1;if(A*(B+C/D)==24&&1.0*C/D==C/D)return 1;if((A*B+C)/D==24&&1.0*(A*B+C)/D==(A*B+C)/D)return 1;if(A*B-C+D==24)return 1;if(A*(B-C)+D==24)return 1;if(A*(B-C+D)==24)return 1;if(A*B-C-D==24)return 1;if(A*(B-C)-D==24)return 1;if(A*(B-C-D)==24)return 1;if(A*B-C*D==24)return 1;if(A*(B-C)*D==24)return 1;if(A*(B-C*D)==24)return 1;if((A*B-C)*D==24)return 1;if(A*B-C/D==24&&1.0*C/D==C/D)return 1;if(A*(B-C)/D==24&&1.0*A*(B-C)/D==A*(B-C)/D)return 1;if(A*(B-C/D)==24&&1.0*C/D==C/D)return 1; if((A*B-C)/D==24&&1.0*(A*B-C)/D==(A*B-C)/D)return 1;if(A*B*C+D==24)return 1;if(A*B*(C+D)==24)return 1;if(A*B*C-D==24)return 1;if(A*B*(C-D)==24)return 1;if(A*B*C*D==24)return 1;if(A*B*C/D==24&&1.0*A*B*C/D==A*B*C/D)return 1;if(A*B/C+D==24&&1.0*A*B/C==A*B/C)return 1;if(A*B/(C+D)==24&&1.0*A*B/(C+D)==A*B/(C+D))return 1;if(A*B/C-D==24&&1.0*A*B/C==A*B/C)return 1;if(C-D!=0&&A*B/(C-D)==24&&1.0*A*B/(C-D)==A*B/(C-D))return 1;if(A*B/C*D==24&&1.0*A*B/C*D==A*B/C*D)return 1;if(A*B/C/D==24&&1.0*A*B/C/D==A*B/C/D)return 1;if(A/B+C+D==24&&1.0*A/B==A/B)return 1;if(A/(B+C)+D==24&&1.0*A/(B+C)==A/(B+C))return 1;if(A/(B+C+D)==24&&1.0*A/(B+C+D)==A/(B+C+D))return 1;if(A/B+C-D==24&&1.0*A/B==A/B)return 1;if(A/(B+C)-D==24&&1.0*A/(B+C)==A/(B+C))return 1;if(B+C-D!=0&&A/(B+C-D)==24&&1.0*A/(B+C-D)==A/(B+C-D))return 1;if(A/B+C*D==24&&1.0*A/B==A/B)return 1;if(A/(B+C)*D==24&&1.0*A/(B+C)*D==A/(B+C)*D)return 1;if(A/(B+C*D)==24&&1.0*A/(B+C*D)==A/(B+C*D))return 1;if(A/B+C/D==24&&1.0*A/B==A/B&&1.0*C/D==C/D)return 1;if(A/(B+C)/D==24&&1.0*A/(B+C)/D==A/(B+C)/D)return 1;if(A/(B+C/D)==24&&1.0*C/D==C/D&&1.0*A/(B+C/D)==A/(B+C/D))return 1;if((A/B+C)/D==24&&1.0*A/B==A/B&&1.0*(A/B+C)/D==(A/B+C)/D)return 1;if(A/B-C+D==24&&1.0*A/B==A/B)return 1;if(B-C!=0&&A/(B-C)+D==24&&1.0*A/(B-C)==A/(B-C))return 1;if(B-C+D!=0&&A/(B-C+D)==24&&1.0*A/(B-C+D)==A/(B-C+D))return 1;if(A/B-C-D==24&&1.0*A/B==A/B)return 1;if(B-C!=0&&A/(B-C)-D==24&&1.0*A/(B-C)==A/(B-C))return 1;if(B-C-D!=0&&A/(B-C-D)==24&&1.0*A/(B-C-D)==A/(B-C-D))return 1;if(A/B-C*D==24&&1.0*A/B==A/B)return 1;if(B-C!=0&&A/(B-C)*D==24&&1.0*A/(B-C)*D==A/(B-C)*D)return 1;if(B-C*D!=0&&A/(B-C*D)==24&&1.0*A/(B-C*D)==A/(B-C*D))return 1;if(A/B-C/D==24&&1.0*A/B==A/B&&1.0*C/D==C/D)return 1;if(B-C!=0&&A/(B-C)/D==24&&1.0*A/(B-C)/D==A/(B-C)/D)return 1;if(B-C/D!=0&&A/(B-C/D)==24&&1.0*C/D==C/D&&1.0*A/(B-C/D)==A/(B-C/D))return 1;if((A/B-C)/D==24&&1.0*A/B==A/B&&1.0*(A/B-C)/D==(A/B-C)/D)return 1;if(A/B*C+D==24&&1.0*A/B*C==A/B*C)return 1;if(A/(B+C)*D==24&&1.0*A/(B+C)*D==A/(B+C)*D)return 1;if(A/(B+C*D)==24&&1.0*A/(B+C*D)==A/(B+C*D))return 1;if(A/B*C-D==24&&1.0*A/B*C==A/B*C)return 1;if(A/B*(C-D)==24&&1.0*A/B*(C-D)==A/B*(C-D))return 1;if(B*C-D!=0&&A/(B*C-D)==24&&1.0*A/(B*C-D)==A/(B*C-D))return 1;if(A/B*C*D==24&&1.0*A/B*C*D==A/B*C*D)return 1;if(A/B*C/D==24&&1.0*A/B*C/D==A/B*C/D)return 1;if(A/B/C+D==24&&1.0*A/B/C==A/B/C)return 1;if(A/B/(C+D)==24&&1.0*A/B/(C+D)==A/B/(C+D))return 1;if(A/B/C-D==24&&1.0*A/B/C==A/B/C)return 1;if(C-D!=0&&A/B/(C-D)==24&&1.0*A/B/(C-D)==A/B/(C-D))return 1;if(A/B/C*D==24&&1.0*A/B/C*D==A/B/C*D)return 1;if(A/B/C/D==24&&1.0*A/B/C/D==A/B/C/D)return 1;return 0; } int main() { #ifdef DEBUGfreopen("input.in", "r", stdin);//freopen("output.out", "w", stdout); #endif//ios::sync_with_stdio(false);//cin.tie(0);//cout.tie(0);//scanf("%d",&t);//while(t--){scanf("%d%d%d%d",&a[1],&a[2],&a[3],&a[4]);ans=0;while(cnt<24){++cnt;next_permutation(a+1,a+5);if(check()){ans=1;break;}}cout<<(ans?"Yes":"No")<<endl;//}#ifdef DEBUGprintf("Time cost : %lf s\n",(double)clock()/CLOCKS_PER_SEC); #endif//cout << "Hello world!" << endl;return 0; }Problem B?Pikachu
比賽地址:http://47.96.116.66/problem.php?cid=1275&pid=1
補(bǔ)題地址:http://47.96.116.66/problem.php?id=2111
題意:
第一種操作對(duì)[l,r]區(qū)間內(nèi)每幢房子塞入一個(gè)皮卡丘; 第二種操作對(duì)第l次到第r次的操作重復(fù)一遍。
問(wèn)依次進(jìn)行m次操作后每幢房子內(nèi)皮卡丘的個(gè)數(shù)。
題解:
可以 O(n)維護(hù)兩個(gè)差分?jǐn)?shù)組,一個(gè)是針對(duì)重復(fù)操作的差分?jǐn)?shù)組,一個(gè)是針對(duì)當(dāng)前房子塞入皮卡丘的個(gè)數(shù)的差分?jǐn)?shù)組。對(duì)第二個(gè)差分?jǐn)?shù)組的每次修改的大小是當(dāng)前操作重復(fù)操作次數(shù)。 因?yàn)槊恳淮蔚诙N操作總是針對(duì)之前的操作,所以要倒著跑一遍。 最后對(duì)針對(duì)當(dāng)前房子塞入皮卡丘的個(gè)數(shù)的差分?jǐn)?shù)組求個(gè)前綴和就好了。
C++版本一
/* *@Author: STZG *@Language: C++ */ #include <bits/stdc++.h> #include<iostream> #include<algorithm> #include<cstdlib> #include<cstring> #include<cstdio> #include<string> #include<vector> #include<bitset> #include<queue> #include<deque> #include<stack> #include<cmath> #include<list> #include<map> #include<set> //#define DEBUG #define RI register int #define endl "\n" using namespace std; typedef long long ll; //typedef __int128 lll; const int N=100000+10; const int M=100000+10; const int MOD=1e9+7; const double PI = acos(-1.0); const double EXP = 1E-8; const int INF = 0x3f3f3f3f; int t,n,m,k,p,l,r,u,v; int ans,cnt,flag,temp,sum; ll a[N],pre[N]; char str; struct node{int l,r,op; }e[N]; int main() { #ifdef DEBUGfreopen("input.in", "r", stdin);//freopen("output.out", "w", stdout); #endif//ios::sync_with_stdio(false);//cin.tie(0);//cout.tie(0);scanf("%d",&t);while(t--){scanf("%d%d",&n,&m);memset(pre,0,sizeof(pre));memset(a,0,sizeof(a));pre[m+1]++;pre[0]--;for(int i=1;i<=m;i++){scanf("%d%d%d",&e[i].op,&e[i].l,&e[i].r);}for(int i=m;i>=1;i--){pre[i]=(pre[i]+pre[i+1])%MOD;if(e[i].op!=1){pre[e[i].r]=(pre[e[i].r]+pre[i])%MOD;pre[e[i].l-1]=(pre[e[i].l-1]-pre[i]+MOD)%MOD;}else{a[e[i].l]=(a[e[i].l]+pre[i])%MOD;a[e[i].r+1]=(a[e[i].r+1]-pre[i]+MOD)%MOD;//cout<<e[i].l<<" "<<e[i].r<<" "<<pre[i]<<endl;}}for(int i=1;i<=n;i++){a[i]=(a[i]+a[i-1])%MOD;}for(int i=1;i<=n;i++){printf("%lld%c",a[i]," \n"[i==n]);}}#ifdef DEBUGprintf("Time cost : %lf s\n",(double)clock()/CLOCKS_PER_SEC); #endif//cout << "Hello world!" << endl;return 0; }Problem C?Raichu
比賽地址:http://47.96.116.66/problem.php?cid=1275&pid=2
補(bǔ)題地址:http://47.96.116.66/problem.php?id=2112
題意:
第一種操作對(duì)第x幢房子塞入一個(gè)呂子喬; 第二種操作對(duì)第x次操作重復(fù)一遍。
問(wèn)依次進(jìn)行m次操作后每幢房子內(nèi)呂子喬的個(gè)數(shù)(初始每幢房子都是空的)。
題解:根據(jù)題意可以得出結(jié)論一個(gè)第二種操作回溯到頭一定是第一種操作,一定是一個(gè)鏈狀的結(jié)構(gòu)。 同時(shí)我們很容易維護(hù)每個(gè)第二種操作的頭節(jié)點(diǎn)是誰(shuí),可以通過(guò)直接繼承前一次操作的頭節(jié)點(diǎn)
C++版本一
/* *@Author: STZG *@Language: C++ */ #include <bits/stdc++.h> #include<iostream> #include<algorithm> #include<cstdlib> #include<cstring> #include<cstdio> #include<string> #include<vector> #include<bitset> #include<queue> #include<deque> #include<stack> #include<cmath> #include<list> #include<map> #include<set> //#define DEBUG #define RI register int #define endl "\n" using namespace std; typedef long long ll; //typedef __int128 lll; const int N=100000+10; const int M=100000+10; const int MOD=1e9+7; const double PI = acos(-1.0); const double EXP = 1E-8; const int INF = 0x3f3f3f3f; int t,n,m,k,p,l,r,u,v; int ans,cnt,flag,temp,sum; int a[N],pre[N]; char str; struct node{}; int main() { #ifdef DEBUGfreopen("input.in", "r", stdin);//freopen("output.out", "w", stdout); #endif//ios::sync_with_stdio(false);//cin.tie(0);//cout.tie(0);scanf("%d",&t);while(t--){scanf("%d%d",&n,&m);memset(a,0,sizeof(a));for(int i=1;i<=m;i++){scanf("%d%d",&u,&v);if(u==1){a[v]++;pre[i]=v;}else{pre[i]=pre[v];a[pre[v]]++;}}for(int i=1;i<=n;i++){printf("%d%c",a[i]," \n"[i==n]);}}#ifdef DEBUGprintf("Time cost : %lf s\n",(double)clock()/CLOCKS_PER_SEC); #endif//cout << "Hello world!" << endl;return 0; }Problem D?本題不用算法
比賽地址:http://47.96.116.66/problem.php?cid=1275&pid=3
補(bǔ)題地址:http://47.96.116.66/problem.php?id=2113
題意:給你三個(gè)數(shù)A,B,C,你需要找到另外三個(gè)數(shù)a,b,c分別是對(duì)應(yīng)A,B,C的因數(shù),請(qǐng)你輸出一共有多少種方案數(shù)(三個(gè)數(shù)順序改變視為同一種方案)
題解:容斥+組合數(shù)學(xué)+狀態(tài)壓縮
無(wú)非只有7種狀況
001:只是A的約數(shù),不是BC的約數(shù),這是可以容斥的。下同。
010:只是B的因數(shù)。
100:只是C的因數(shù)。
011:只是AB的因數(shù)。
101:只是AC的因數(shù)。
110:只是BC的因數(shù)。
111:同時(shí)是ABC的因數(shù)
我們現(xiàn)在就可以枚舉每條邊的狀態(tài)了,三重循環(huán)7*7*7次。那么接下來(lái)我們考慮什么樣的邊是滿足條件的邊呢:
給小長(zhǎng)方體一個(gè)合適的翻轉(zhuǎn),使三條邊至少分別是ABC點(diǎn)的因子。怎么做呢?上面我們按位處理了每條邊的狀態(tài),所以只要沒(méi)枚舉一下變得順序(翻轉(zhuǎn)正方形)使得和ABC一一對(duì)應(yīng)(對(duì)應(yīng)位為1)
bool check(int a,int b,int c){if((a&1) && (b&2) && (c&4))return true;if((a&1) && (c&2) && (b&4))return true;if((b&1) && (a&2) && (c&4))return true;if((b&1) && (c&2) && (a&4))return true;if((c&1) && (a&2) && (b&4))return true;if((c&1) && (b&2) && (a&4))return true;return false; }
好了接下來(lái)我們找到合適的三邊了,那么怎么計(jì)算此時(shí)的種類(lèi)呢?這也是本體的一大亮點(diǎn)。
1.如果a,b,c是不同的狀態(tài)得來(lái)的,那么ok沒(méi)有重復(fù)。每種數(shù)量選一個(gè),也就是乘起來(lái)就好啦~
2.但是如果有兩個(gè)數(shù)或者三個(gè)數(shù)是相同的狀態(tài),這就要求我們從一定數(shù)量中選擇有重復(fù)個(gè)元素。舉個(gè)例子,如果ab狀態(tài)相同,都是cond[s],那么我們應(yīng)該從cond[s]中選兩個(gè),并且可以重復(fù)即a選了k,b也選了k
這就需用到有重復(fù)的組合公式:
如果從n個(gè)元素中選擇r個(gè)有重復(fù)元素,其公式為:
另外,我們用use數(shù)組將計(jì)算過(guò)程一般化,use[i]即為r。請(qǐng)好好體會(huì)。這里非常巧妙。
參考文章:原題?原博客
C++版本一
#include<iostream> #include<cstdio> #include<cstring> typedef long long ll; using namespace std;const int maxn = 1e5 + 10; int fac[maxn];void fac_table(int n){for(int i = 1;i < n;i++)for(int j = i;j < n;j+=i)fac[j]++;return; } ll C(int n,int m){ll ans = 1;for(int i = 1;i <= m;i++){ans = ans*(n-i+1)/i;}return ans; }int gcd(int a,int b){if(b == 0)return a;return gcd(b,a%b); }bool check(int a,int b,int c){if((a&1) && (b&2) && (c&4))return true;if((a&1) && (c&2) && (b&4))return true;if((b&1) && (a&2) && (c&4))return true;if((b&1) && (c&2) && (a&4))return true;if((c&1) && (a&2) && (b&4))return true;if((c&1) && (b&2) && (a&4))return true;return false; }int condi[10],use[10];int main(){fac_table(maxn);ll T;int x,y,z;ll ans;scanf("%lld",&T);while(T--){scanf("%d%d%d",&x,&y,&z);int xy = gcd(x,y);int xz = gcd(x,z);int yz = gcd(y,z);int xyz = gcd(xy,z);condi[1] = fac[x] - fac[xy] - fac[xz] + fac[xyz];//001condi[2] = fac[y] - fac[xy] - fac[yz] + fac[xyz];//010condi[4] = fac[z] - fac[xz] - fac[yz] + fac[xyz];//100condi[3] = fac[xy] - fac[xyz];//011condi[5] = fac[xz] - fac[xyz];//101condi[6] = fac[yz] - fac[xyz];//110condi[7] = fac[xyz];ans = 0;for(int a = 1;a < 8;a++)for(int b = a;b < 8;b++)for(int c = b;c < 8;c++)if(check(a,b,c) == true){memset(use,0,sizeof(use));use[a]++;use[b]++;use[c]++;ll tmp = 1;for(int i = 1;i < 8;i++)if(use[i] != 0)tmp = tmp*C(condi[i] + use[i]-1,use[i]);if(tmp > 0)ans += tmp;}printf("%lld\n",ans);}return 0; }Problem E?博弈
比賽地址:http://47.96.116.66/problem.php?cid=1275&pid=4
補(bǔ)題地址:http://47.96.116.66/problem.php?id=2114
題意:小A和小B進(jìn)行一場(chǎng)博弈,有一個(gè)串有n顆珠子的圓環(huán),每次一個(gè)人可以取走連續(xù)的1顆或2顆,問(wèn)誰(shuí)會(huì)贏。
題解:如果是1或2,那么小A取走直接贏,否則小B贏,因?yàn)樗梢宰兂蓪?duì)稱(chēng)博弈。
C++版本一
/* *@Author: STZG *@Language: C++ */ #include <bits/stdc++.h> #include<iostream> #include<algorithm> #include<cstdlib> #include<cstring> #include<cstdio> #include<string> #include<vector> #include<bitset> #include<queue> #include<deque> #include<stack> #include<cmath> #include<list> #include<map> #include<set> //#define DEBUG #define RI register int #define endl "\n" using namespace std; typedef long long ll; //typedef __int128 lll; const int N=100000+10; const int M=100000+10; const int MOD=1e9+7; const double PI = acos(-1.0); const double EXP = 1E-8; const int INF = 0x3f3f3f3f; int t,n,m,k,p,l,r,u,v; int ans,cnt,flag,temp,sum; int a[N]; char str; struct node{}; int main() { #ifdef DEBUGfreopen("input.in", "r", stdin);//freopen("output.out", "w", stdout); #endif//ios::sync_with_stdio(false);//cin.tie(0);//cout.tie(0);//scanf("%d",&t);//while(t--){scanf("%d",&n);cout<<(n==1||n==2?'A':'B')<<endl;//}#ifdef DEBUGprintf("Time cost : %lf s\n",(double)clock()/CLOCKS_PER_SEC); #endif//cout << "Hello world!" << endl;return 0; }Problem F?地下迷宮
比賽地址:http://47.96.116.66/problem.php?cid=1275&pid=5
補(bǔ)題地址:http://47.96.116.66/problem.php?id=2115
題意:任意兩點(diǎn)之間最短路
題解:先建成一顆生成樹(shù),然后對(duì)于剩下的邊的所有點(diǎn)跑一邊最短路,記錄下這些點(diǎn)到其他所有點(diǎn)的距離,然后跑樹(shù)上最短路,再暴力枚舉剩下的邊,取距離最小值。
C++版本一
/* *@Author: STZG *@Language: C++ */ #include <bits/stdc++.h> #include<iostream> #include<algorithm> #include<cstdlib> #include<cstring> #include<cstdio> #include<string> #include<vector> #include<bitset> #include<queue> #include<deque> #include<stack> #include<cmath> #include<list> #include<map> #include<set> //#define DEBUG #define RI register int #define endl "\n" using namespace std; typedef long long ll; //typedef __int128 lll; const int N=100000+10; const int M=100000+10; const int MOD=1e9+7; const double PI = acos(-1.0); const double EXP = 1E-8; const int INF = 0x3f3f3f3f; int t,n,m,k,p,l,r,u,v,w; ll ans,cnt,flag,temp,sum; int dp[23][N]; ll dis[N]; ll dep[N]; int pre[N]; bool vis[N]; ll dist[30][N]; int tag[N]; char str; struct node{int u,v;ll w;bool vis;node(){ };node(int u,int v ,ll w):u(u),v(v),w(w),vis(0){ }bool operator <(const node &S)const{return w<S.w;} }e[N],tmp[30]; int find(int x){return pre[x]==x?x:pre[x]=find(pre[x]);} vector<node>G[N]; void dfs(int u){vis[u]=1;for(int i=0,j=G[u].size();i<j;i++){int v=G[u][i].v;if(vis[v]==0){dp[0][v]=u;dep[v]=dep[u]+1;dis[v]=dis[u]+G[u][i].w;dfs(v);}} } int LCA(int x,int y){if(dep[x]<dep[y])swap(x,y);while(dep[x]>dep[y]){x=dp[(int)log2(dep[x]-dep[y])][x];}if(x==y)return x;for(int i=log2(dep[x]);i>=0;i--){if(dp[i][x]!=dp[i][y]){x=dp[i][x];y=dp[i][y];}}return dp[0][x]; } void spfa(int u,ll *dist){memset(vis,0,sizeof(vis));dist[u]=0;queue<int>q;q.push(u);vis[u]=1;while(!q.empty()){int u=q.front();q.pop();vis[u]=0;for(int i=0,j=G[u].size();i<j;i++){node e=G[u][i];if(dist[e.v]>dist[u]+e.w){dist[e.v]=dist[u]+e.w;if(vis[e.v]==0){q.push(e.v);vis[e.v]=1;}}}} } int main() { #ifdef DEBUGfreopen("input.in", "r", stdin);//freopen("output.out", "w", stdout); #endif//ios::sync_with_stdio(false);//cin.tie(0);//cout.tie(0);//scanf("%d",&t);//while(t--){scanf("%d%d",&n,&m);for(int i=1;i<=n;i++)pre[i]=i;for(int i=1;i<=m;i++){scanf("%d%d%lld",&e[i].u,&e[i].v,&e[i].w);}sort(e+1,e+m+1);for(int i=1;i<=m;i++){u=e[i].u;v=e[i].v;w=e[i].w;int tx=find(u);int ty=find(v);if(tx!=ty){pre[tx]=ty;e[i].vis=1;G[u].push_back({u,v,w});G[v].push_back({v,u,w});}else{tmp[++sum]=e[i];}}for(int i=1;i<=n;i++){if(vis[i]==0)dfs(i);}for(int i=0;i<22;i++){for(int j=1;j<=n;j++){dp[i+1][j]=dp[i][dp[i][j]];}}for(int i=1;i<=sum;i++){if(tmp[i].vis==0){u=tmp[i].u;v=tmp[i].v;w=tmp[i].w;G[u].push_back({u,v,w});G[v].push_back({v,u,w});}}memset(dist,0x3f,sizeof(dist));for(int i=1;i<=sum;i++){if(tmp[i].vis==0){if(tag[tmp[i].u]==0){tag[tmp[i].u]=++cnt;spfa(tmp[i].u,dist[cnt]);}if(tag[tmp[i].v]==0){tag[tmp[i].v]=++cnt;spfa(tmp[i].v,dist[cnt]);}}}scanf("%d",&k);while(k--){scanf("%d%d",&u,&v);ans=dis[u]+dis[v]-2*dis[LCA(u,v)];for(int i=1;i<=sum;i++){ll x=dist[tag[tmp[i].u]][u];ll y=dist[tag[tmp[i].v]][v];ans=min(ans,x+y+tmp[i].w);x=dist[tag[tmp[i].u]][v];y=dist[tag[tmp[i].v]][u];ans=min(ans,x+y+tmp[i].w);}cout<<ans<<endl;}//}#ifdef DEBUGprintf("Time cost : %lf s\n",(double)clock()/CLOCKS_PER_SEC); #endif//cout << "Hello world!" << endl;return 0; }Problem G?簡(jiǎn)簡(jiǎn)單單的數(shù)學(xué)題
比賽地址:http://47.96.116.66/problem.php?cid=1275&pid=6
補(bǔ)題地址:http://47.96.116.66/problem.php?id=2116
題意:?a? +?b?+c(四舍五入)+d^n
題解:快速冪+乘法優(yōu)化
C++版本一
題解:快速冪+__int128
/* *@Author: STZG *@Language: C++ */ #include <bits/stdc++.h> #include<iostream> #include<algorithm> #include<cstdlib> #include<cstring> #include<cstdio> #include<string> #include<vector> #include<bitset> #include<queue> #include<deque> #include<stack> #include<cmath> #include<list> #include<map> #include<set> //#define DEBUG #define RI register int #define endl "\n" using namespace std; typedef long long ll; //typedef __int128 lll; const int N=100000+10; const int M=100000+10; const ll MOD=1e12; const double PI = acos(-1.0); const double EXP = 1E-8; const int INF = 0x3f3f3f3f; ll t,n,m,k,p,l,r,u,v; int ans,cnt,flag,temp,sum; double a,b,c; ll d; char str; struct node{}; ll POW(ll a,ll b,ll c){__int128 res=1;__int128 base=a%c;while(b){if(b&1)res=(res*base)%c;base=(base*base)%c;b>>=1;}return res; } int main() { #ifdef DEBUGfreopen("input.in", "r", stdin);//freopen("output.out", "w", stdout); #endif//ios::sync_with_stdio(false);//cin.tie(0);//cout.tie(0);//scanf("%d",&t);//while(t--){//scanf("%d",&n);scanf("%lf%lf%lf",&a,&b,&c);ll A=a;ll B=b;if(b-B>0)B++;ll C=c+0.5;scanf("%lld",&k);while(k--){scanf("%lld%lld",&d,&n);printf("%lld\n",(((A+B)%MOD+C)%MOD+POW(d,n,MOD))%MOD);}//}#ifdef DEBUGprintf("Time cost : %lf s\n",(double)clock()/CLOCKS_PER_SEC); #endif//cout << "Hello world!" << endl;return 0; }C++版本二
快速冪+乘法優(yōu)化,變成1e6進(jìn)制的數(shù)
?
Problem H?拼可可
比賽地址:http://47.96.116.66/problem.php?cid=1275&pid=7
補(bǔ)題地址:http://47.96.116.66/problem.php?id=2117
題意:至少多少個(gè)a*b的矩形才能拼成一個(gè)正方形?
題解:求a,b的lcm即可
C++版本一
/* *@Author: STZG *@Language: C++ */ #include <bits/stdc++.h> #include<iostream> #include<algorithm> #include<cstdlib> #include<cstring> #include<cstdio> #include<string> #include<vector> #include<bitset> #include<queue> #include<deque> #include<stack> #include<cmath> #include<list> #include<map> #include<set> //#define DEBUG #define RI register int #define endl "\n" using namespace std; typedef long long ll; //typedef __int128 lll; const int N=100000+10; const int M=100000+10; const int MOD=1e9+7; const double PI = acos(-1.0); const double EXP = 1E-8; const int INF = 0x3f3f3f3f; ll t,n,m,k,p,l,r,u,v; int ans,cnt,flag,temp,sum; int a[N]; char str; struct node{}; int main() { #ifdef DEBUGfreopen("input.in", "r", stdin);//freopen("output.out", "w", stdout); #endif//ios::sync_with_stdio(false);//cin.tie(0);//cout.tie(0);//scanf("%d",&t);//while(t--){scanf("%lld%lld",&n,&m);ll gcd=__gcd(n,m);printf("%lld\n",(n/gcd)*(m/gcd));//}#ifdef DEBUGprintf("Time cost : %lf s\n",(double)clock()/CLOCKS_PER_SEC); #endif//cout << "Hello world!" << endl;return 0; }Problem I?簽到題
比賽地址:http://47.96.116.66/problem.php?cid=1275&pid=8
補(bǔ)題地址:http://47.96.116.66/problem.php?id=2118
題意:
題解:二分答案,差分檢查。
C++版本一
/* *@Author: STZG *@Language: C++ */ #include <bits/stdc++.h> #include<iostream> #include<algorithm> #include<cstdlib> #include<cstring> #include<cstdio> #include<string> #include<vector> #include<bitset> #include<queue> #include<deque> #include<stack> #include<cmath> #include<list> #include<map> #include<set> //#define DEBUG #define RI register int #define endl "\n" using namespace std; typedef long long ll; //typedef __int128 lll; const int N=200000+10; const int M=100000+10; const int MOD=1e9+7; const double PI = acos(-1.0); const double EXP = 1E-8; const int INF = 0x3f3f3f3f; int t,n,m,k,p,l,r,u,v,w; int ans,cnt,flag,temp,sum; int a[N],b[N]; char str; struct node{}; bool sloved(int mid){memset(b,0,sizeof(b));sum=0;for(int i=1;i<=n;i++){b[i]+=b[i-1];if(a[i]+b[i]<mid){int temp=mid-a[i]-b[i];b[i]+=temp;b[min(n+1,i+w)]-=temp;sum+=temp;}}return sum<=m; } int main() { #ifdef DEBUGfreopen("input.in", "r", stdin);//freopen("output.out", "w", stdout); #endif//ios::sync_with_stdio(false);//cin.tie(0);//cout.tie(0);scanf("%d",&t);while(t--){scanf("%d%d%d",&n,&m,&w);int l=INF;int r=-INF;for(int i=1;i<=n;i++){scanf("%d",&a[i]);l=min(l,a[i]);r=max(r,a[i]+m);}while(l<=r){int mid=(l+r)>>1;if(sloved(mid)){ans=mid;l=mid+1;}else{r=mid-1;}}cout<<ans<<endl;}#ifdef DEBUGprintf("Time cost : %lf s\n",(double)clock()/CLOCKS_PER_SEC); #endif//cout << "Hello world!" << endl;return 0; }Problem J?無(wú)盡遞增
比賽地址:http://47.96.116.66/problem.php?cid=1275&pid=9
補(bǔ)題地址:http://47.96.116.66/problem.php?id=2119
題意:找一個(gè)最長(zhǎng)的子序列,1111122222.
題解:DP
轉(zhuǎn)化題意后,其實(shí)就是找出最長(zhǎng)的1111222211112222,我們可以開(kāi)dp【4】,分別表示以紅色標(biāo)出的值為結(jié)尾的最長(zhǎng)子序列。
轉(zhuǎn)移公式為:
C++版本一
/* *@Author: STZG *@Language: C++ */ #include <bits/stdc++.h> #include<iostream> #include<algorithm> #include<cstdlib> #include<cstring> #include<cstdio> #include<string> #include<vector> #include<bitset> #include<queue> #include<deque> #include<stack> #include<cmath> #include<list> #include<map> #include<set> //#define DEBUG #define RI register int #define endl "\n" using namespace std; typedef long long ll; //typedef __int128 lll; const int N=200000+10; const int M=100000+10; const int MOD=1e9+7; const double PI = acos(-1.0); const double EXP = 1E-8; const int INF = 0x3f3f3f3f; int t,n,m,k,p,l,r,u,v; int ans,cnt,flag,temp,sum; int a[N],dp[5]; char str; struct node{}; int main() { #ifdef DEBUGfreopen("input.in", "r", stdin);//freopen("output.out", "w", stdout); #endif//ios::sync_with_stdio(false);//cin.tie(0);//cout.tie(0);scanf("%d",&t);while(t--){scanf("%d",&n);memset(dp,0,sizeof(dp));for(int i=1;i<=n;i++){scanf("%d",&a[i]);dp[1]=dp[1]+(a[i]==1);dp[2]=max(dp[1],dp[2]+(a[i]==2));dp[3]=max(dp[2],dp[3]+(a[i]==1));dp[4]=max(dp[3],dp[4]+(a[i]==2));}cout<<dp[4]<<endl;}#ifdef DEBUGprintf("Time cost : %lf s\n",(double)clock()/CLOCKS_PER_SEC); #endif//cout << "Hello world!" << endl;return 0; }Problem K?消消樂(lè)
比賽地址:http://47.96.116.66/problem.php?cid=1275&pid=10
補(bǔ)題地址:http://47.96.116.66/problem.php?id=2120
題意:
題解:區(qū)間dp + 記憶化搜索
dp[i][j][k] : (區(qū)間 [i,? j] 后面帶上一段和 j 顏色相同的且長(zhǎng)度為 k )的消消樂(lè)最大積分
1.消最后一段顏色和 j 顏色相同的
dp[i][j][k] <-- dp[i][j-1][0] + (k+1)^3
2.對(duì)于i <= l < j, 如果 l 和 j 的顏色相同, 那么可以把 [l+1, j-1]消掉, 那么剩下的一段就有 k+1 個(gè)和 l 相同的一段了
dp[i][j][k] <-- dp[i][l][k+1] + dp[l+1][j-1][0]
答案就是dp[1][n][0],采用記憶化搜索更方便轉(zhuǎn)移
C++版本一
?
Problem L?尋寶
比賽地址:http://47.96.116.66/problem.php?cid=1275&pid=11
補(bǔ)題地址:http://47.96.116.66/problem.php?id=2121
題意:
題解:
Exkmp預(yù)處理出數(shù)組,后綴數(shù)組也行,查詢由于強(qiáng)制在線主席樹(shù)順便搞搞就好,對(duì)于會(huì)這兩個(gè)算法的人這題應(yīng)該是一道一眼題,而且由于懶得造數(shù)據(jù),所以數(shù)據(jù)都是循環(huán)的,說(shuō)不定有什么優(yōu)秀的暴力也能過(guò)
C++版本一
?
Problem M?智慧爺?shù)牡案?/h3>
比賽地址:http://47.96.116.66/problem.php?cid=1275&pid=12
補(bǔ)題地址:http://47.96.116.66/problem.php?id=2122
題意:求后綴子串的最長(zhǎng)公共前綴子串
題解:SA+LCP+ST
(方法一)?后綴數(shù)組 ST表預(yù)處理 復(fù)雜度 nlogn
(方法二) 字符串哈希+二分 qlog(n)+n
C++版本一
題解:后綴數(shù)組 ST表預(yù)處理
/* *@Author: STZG *@Language: C++ */ #include <bits/stdc++.h> #include<iostream> #include<algorithm> #include<cstdlib> #include<cstring> #include<cstdio> #include<string> #include<vector> #include<bitset> #include<queue> #include<deque> #include<stack> #include<cmath> #include<list> #include<map> #include<set> //#define DEBUG #define RI register int #define endl "\n" using namespace std; typedef long long ll; //typedef __int128 lll; const int N=200000+10; const int M=100000+10; const int MOD=1e9+7; const double PI = acos(-1.0); const double EXP = 1E-8; const int INF = 0x3f3f3f3f; int t,n,m,k,p,u,v,q; int ans,cnt,flag,temp,sum; char str[N]; /*da(str ,sa,rank,height,n ,128);//n是字符串長(zhǎng)度; *例如: *n = 8,實(shí)際元素有9個(gè),最后加上一個(gè)$ (即最小字符) *num[] = { 1, 1, 2, 1, 1, 1, 1, 2, $ };注意num最后一位為0,其他大于0 *rank[] = { 4, 6, 8, 1, 2, 3, 5, 7, 0 };rank[0~n-1]為有效值,rank[n]必定為0無(wú)效值 *sa[]= { 8, 3, 4, 5, 0, 6, 1, 7, 2 };sa[1~n]為有效值,sa[0]必定為n是無(wú)效值 *height[]= { 0, 0, 3, 2, 3, 1, 2, 0, 1 };height[2~n]為有效值 */ int t1[N],t2[N],c[N];//求SA數(shù)組需要的中間變量,不需要賦值 //待排序的字符串放在s數(shù)組中,從s[0]到s[n-1],長(zhǎng)度為n,且最大值小于m, //除s[n-1]外的所有s[i]都大于0,r[n-1]=0 //函數(shù)結(jié)束以后結(jié)果放在sa數(shù)組中,sa數(shù)組下標(biāo)范圍1~n bool cmp(int *r,int a,int b,int l) {return r[a] == r[b] && r[a+l] == r[b+l]; } void da(int str[],int sa[],int rank1[],int height[],int n,int m) { //n是串長(zhǎng)度,m是字符集大小,一般128n++;int i, j, p, *x = t1, *y = t2;//第一輪基數(shù)排序,如果s的最大值很大,可改為快速排序for(i = 0; i < m; i++)c[i] = 0;for(i = 0; i < n; i++)c[x[i] = str[i]]++;for(i = 1; i < m; i++)c[i] += c[i-1];for(i = n-1; i >= 0; i--)sa[--c[x[i]]] = i;for(j = 1; j <= n; j <<= 1) {p = 0;//直接利用sa數(shù)組排序第二關(guān)鍵字for(i = n-j; i < n; i++)y[p++] = i;//后面的j個(gè)數(shù)第二關(guān)鍵字為空的最小for(i = 0; i < n; i++)if(sa[i] >= j)y[p++] = sa[i] - j;//這樣數(shù)組y保存的就是按照第二關(guān)鍵字排序的結(jié)果//基數(shù)排序第一關(guān)鍵字for(i = 0; i < m; i++)c[i] = 0;for(i = 0; i < n; i++)c[x[y[i]]]++;for(i = 1; i < m; i++)c[i] += c[i-1];for(i = n-1; i >= 0; i--)sa[--c[x[y[i]]]] = y[i];//根據(jù)sa和x數(shù)組計(jì)算新的x數(shù)組swap(x,y);p = 1;x[sa[0]] = 0;for(i = 1; i < n; i++)x[sa[i]] = cmp(y,sa[i-1],sa[i],j)?p-1:p++;if(p >= n)break;m = p;//下次基數(shù)排序的最大值}int k = 0;n--;for(i = 0; i <= n; i++)rank1[sa[i]] = i;for(i = 0; i < n; i++) {if(k)k--;j = sa[rank1[i]-1];while(str[i+k] == str[j+k])k++;height[rank1[i]] = k;} } int rank1[N],height[N]; int RMQ[N]; int mm[N]; int best[23][N]; void initRMQ(int n) { //調(diào)用da后,初始化RMQ(求LCP用)for(int i=1;i<=n;i++)RMQ[i]=height[i];mm[0]=-1;for(int i=1; i<=n; i++)mm[i]=((i&(i-1))==0)?mm[i-1]+1:mm[i-1];for(int i=1; i<=n; i++)best[0][i]=i;for(int i=1; i<=mm[n]; i++)for(int j=1; j+(1<<i)-1<=n; j++) {int a=best[i-1][j];int b=best[i-1][j+(1<<(i-1))];if(RMQ[a]<RMQ[b])best[i][j]=a;else best[i][j]=b;} } int askRMQ(int a,int b) {int t;t=mm[b-a+1];b-=(1<<t)-1;a=best[t][a];b=best[t][b];return RMQ[a]<RMQ[b]?a:b; } int lcp(int a,int b) {a=rank1[a];b=rank1[b];if(a>b)swap(a,b);return height[askRMQ(a+1,b)]; } int r[N]; //把字符串存到這個(gè)數(shù)組里 int sa[N]; //后綴數(shù)組 int main() { #ifdef DEBUGfreopen("input.in", "r", stdin);//freopen("output.out", "w", stdout); #endif//ios::sync_with_stdio(false);//cin.tie(0);//cout.tie(0);//scanf("%d",&t);//while(t--){scanf("%d",&n);cin>>str;for(int i=0;i<n;i++)r[i]=str[i];r[n]='$';da(r,sa,rank1,height,n,128);initRMQ(n);scanf("%d",&q);int a,b,c,d;while(q--){scanf("%d%d%d%d",&a,&b,&c,&d);cout<<(a==c?min(b-a+1,d-c+1):min(min(b-a+1,d-c+1),lcp(a,c)))<<endl;}//}#ifdef DEBUGprintf("Time cost : %lf s\n",(double)clock()/CLOCKS_PER_SEC); #endif//cout << "Hello world!" << endl;return 0; }?
總結(jié)
以上是生活随笔為你收集整理的浙江理工大学2019年5月赛的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 最长不下降子序列问题
- 下一篇: 员工(类的多态性实验)