The Preliminary Contest for ICPC China Nanchang National Invitational
Problem A?PERFECT NUMBER PROBLEM
https://nanti.jisuanke.com/t/38220
題解:打表
/* *@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);printf("6\n28\n496\n8128\n33550336\n");//}#ifdef DEBUGprintf("Time cost : %lf s\n",(double)clock()/CLOCKS_PER_SEC); #endif//cout << "Hello world!" << endl;return 0; }Problem B?Greedy HOUHOU
https://nanti.jisuanke.com/t/38221
Problem C?Angry FFF Party
https://nanti.jisuanke.com/t/38222
題意:f(x)是斐波那契數的第x項,g(x)=f(f(x)),對于給定的n,將其表示成若干個g數的和,要求字典序最小,n<10^100000
題解:矩陣快速冪求一下f(x),預處理前29項g(x)。
可以發現g(x)的增長速度非常快,其實在第29項就已經超出10^100000,由于后面的項差過大,所以方法基本唯一,所以就把貪心選一下,然后前幾項在特判一下取個最小字典序就ok了。
JAVA版本一
Problem D?Match Stick Game
https://nanti.jisuanke.com/t/38223
題解:
先將表達式表示成用最少火柴棍能表達的形式,然后在此基礎上添加火柴棍。
先預處理出i位數添加j個火柴棍能夠得到的最大值,然后背包一下就ok了。
舉個例子
1+1+222
最簡表示1-1-111,剩余11根棒子。
一共三項,1,-1,-111,然后dp[i][j]表示前i項加j根棒子的和的最大值,轉移顯然。
關鍵是預處理比較麻煩。
#include <bits/stdc++.h> #define my_max(a, b) ((a) > (b) ? (a) : (b)) #define my_min(a, b) ((a) < (b) ? (a) : (b)) #define fi first #define se second #define pb push_back #define eb emplace_back #define rep(i, s, t) for(int i = (int)(s); i <= (int)(t); i++) #define rev(i, t, s) for(int i = (int)(t); i >= (int)(s); i--) #define lson rt << 1 #define rson rt << 1 | 1 #define sz(x) (int)(x).size()typedef long long ll; typedef long double lb; typedef std::pair<int, int> pii; typedef std::pair<ll, ll> pll; typedef std::vector<int> VI; typedef std::vector<ll> VL; #include <ext/pb_ds/tree_policy.hpp> #include <ext/pb_ds/assoc_container.hpp> using namespace __gnu_pbds; using namespace std; typedef tree<int,null_type,less<int>,rb_tree_tag,tree_order_statistics_node_update> rbtree; ll gcd(ll x, ll y){ return y % x == 0 ? x : gcd(y % x, x); } template<class T>T my_abs(T a){ if(a < 0) a = -a; return a; } inline ll read(){ll ret = 0, sign = 1;char c = getchar();while(c < '0' || c > '9'){ if(c == '-') sign = -1; c = getchar();}while(c >= '0' && c <= '9'){ ret = ret * 10 + c - '0'; c = getchar(); }return ret * sign; } inline void write(ll x){if(x < 0){putchar('-');x = -x;}if(x > 9) write(x / 10);putchar(x % 10 + '0'); }//void expand_stack_space(){ // int size = 256 << 20; // 256MB // char *p = (char*)malloc(size) + size; // __asm__("movl %0, %%esp\n" :: "r"(p)); //} const int maxn = 100 + 7; const ll inf = 1e18; ll dp[maxn][maxn * 10], sa[maxn]; ll a[maxn][maxn], b[maxn][maxn]; int n; char str[maxn]; int count(char c){if(c == '-' || c == '1') return 0;if(c == '7' || c == '+') return 1;if(c == '4') return 2;if(c == '2' || c == '3' || c == '5') return 3;if(c == '0' || c == '6' || c == '9') return 4;if(c == '8') return 5; } char icount(int c){if(c == 1) return '7';if(c == 2) return '4';if(c == 3) return '5';if(c == 4) return '9';if(c == 5) return '8'; } void init(){for(int i = 1; i <= 10; i++){for(int j = 0; j <= 5 * i; j++){int c = j;string s = "";for(int k = 1; k <= i; k++){if(c >= count('9')) s += '9', c -= count('9');else if(c >= count('7')) s += '7', c -= count('7');else s += '1';}for(int k = i; k >= 1; k--){if(c == 0) break;c += count(s[k - 1]);if(c >= count('8')) s[k - 1] = '8', c -= count('8');else{s[k - 1] = icount(c);c = 0;}}ll res = 0;//cout<<"s " + s<<endl;for(char ss : s) res = res * 10 + ss - '0';a[i][j] = res;b[i][j + 1] = res;}b[i][0] = -b[i][1];} } int main(){ #ifndef ONLINE_JUDGE // freopen("in.txt", "r", stdin); // freopen("out.txt", "w", stdout); #endif // ONLINE_JUDGEint T;init();scanf("%d", &T);while(T--){scanf("%d", &n);scanf("%s", str);int cnt = 0;for(int i = 0; i < n; i++) cnt += count(str[i]);int num = 0, tot = 0;for(int i = 0; i < n; i++){if(str[i] == '-' || str[i] == '+'){sa[++tot] = num;num = 0;}else num++;}//printf("cnt %d\n", cnt);sa[++tot] = num;for(int i = 0; i <= tot; i++) for(int j = 0; j <= cnt; j++) dp[i][j] = -inf;//比賽時初始化寫錯了, 還過了。emmmmdp[0][0] = 0;for(int i = 1; i <= tot; i++){int len = sa[i];//printf("len %d\n", len);if(i == 1){for(int k = 0; k <= 5 * len; k++){for(int j = cnt; j >= k; j--){dp[i][j] = max(dp[i][j], dp[i - 1][j - k] + a[len][k]);}}}else{for(int k = 0; k <= 5 * len; k++){for(int j = cnt; j >= k; j--){dp[i][j] = max(dp[i][j], dp[i - 1][j - k] + b[len][k]);}}}}printf("%lld\n", dp[tot][cnt]);}return 0; }Problem E?Card Game
https://nanti.jisuanke.com/t/38224
Problem F?Information Transmitting
https://nanti.jisuanke.com/t/A2254
Problem G tsy's number
https://nanti.jisuanke.com/t/38226
題解:
#include <cstdio> #include <algorithm> #include <cstring> #include <iostream> using namespace std;typedef unsigned int ll;const int N = 1e7 + 10;int prime[N], phi[N], tot; ll f[N], gg[N], fu[N], res[N]; bool is_prime[N];void init() {memset(is_prime, true, sizeof(is_prime));for (ll i = 1; i < N; i++)f[i] = f[i - 1] + 1;for (ll i = 1; i < N; i++) {gg[i] = gg[i - 1] + i;f[i] = f[i] * gg[i];}for (ll i = 1; i < N; i++) {gg[i] = gg[i - 1] + i * i;f[i] = f[i] * gg[i];}phi[1] = gg[1] = fu[1] = 1;for (int i = 2; i < N; i++) {if (is_prime[i]) {prime[tot++] = i;fu[i] = i;phi[i] = i - 1;gg[i] = i - 2;}for (int j = 0; j < tot && i * prime[j] < N; j++) {is_prime[i * prime[j]] = false;if (i % prime[j] == 0) {phi[i * prime[j]] = phi[i] * prime[j];fu[i * prime[j]] = fu[i] * prime[j];if (fu[i] == i) {gg[i * prime[j]] = phi[i * prime[j]] - phi[i];}else {gg[i * prime[j]] = gg[i / fu[i]] * gg[fu[i * prime[j]]];}break;}else {fu[i * prime[j]] = prime[j];phi[i * prime[j]] = phi[i] * phi[prime[j]];gg[i * prime[j]] = gg[i] * gg[prime[j]];}}}for (ll i = 1; i < N; i++) {res[i] = i * i * i * gg[i] + res[i - 1];} }int n;void solve() {ll ans = 0;for (ll l = 1, r; l <= n; l = r + 1) {r = n / (n / l);ans += (res[r] - res[l - 1]) * f[n / l];}printf("%d\n", ans % (1 << 30)); }int main() {//freopen("0in.txt", "r", stdin);init();int T;scanf("%d", &T);while (T--) {scanf("%d", &n);solve();}return 0; }Problem H?Coloring Game
https://nanti.jisuanke.com/t/38227
題解:快速冪+規律
/* *@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{};ll POW(ll a,ll b,ll c){ll res=1;ll 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);if(n==1){cout<<1<<endl;return 0;}cout<<(4*POW(3,n-2,MOD))%MOD<<endl;//}#ifdef DEBUGprintf("Time cost : %lf s\n",(double)clock()/CLOCKS_PER_SEC); #endif//cout << "Hello world!" << endl;return 0; }Problem I?Max answer
https://nanti.jisuanke.com/t/38228
題意:求區間最小值×區間和的最大值。
題解:用單調棧維護以每個數為最小值能拓展到最左邊和最右邊。然后用線段樹維護一個前綴和。
對于一個數如果是正數查詢當前位置到最右端的前綴和最大值,然后查詢最左端到當前點的最小值做減法。
對于一個數如果是負數查詢正好和上述情況相反。
C++版本一
#include<bits/stdc++.h> using namespace std; #define LL long long #define sca(x) scanf("%d",&x) #define N 500005 const LL inf = 1e18;int a[N],L[N],R[N]; LL sum[N]; stack<int>S; struct node {LL mmax,mmin; }T[N*4];void build(int rt,int l,int r) {if(l==r){T[rt].mmax=sum[l];T[rt].mmin=sum[l];return ;}int m=(l+r)>>1;build(rt<<1,l,m);build(rt<<1|1,m+1,r);T[rt].mmax=max(T[rt<<1].mmax,T[rt<<1|1].mmax);T[rt].mmin=min(T[rt<<1].mmin,T[rt<<1|1].mmin); }LL query_max(int rt,int l,int r,int ql,int qr) {if(l>=ql && r<=qr){return T[rt].mmax;}int m=(l+r)>>1;LL ans1=-inf,ans2=-inf;if(ql<=m) ans1=query_max(rt<<1,l,m,ql,qr);if(qr>m) ans2=query_max(rt<<1|1,m+1,r,ql,qr);return max(ans1,ans2); }LL query_min(int rt,int l,int r,int ql,int qr) {if(l>=ql && r<=qr){return T[rt].mmin;}int m=(l+r)>>1;LL ans1=inf,ans2=inf;if(ql<=m) ans1=query_min(rt<<1,l,m,ql,qr);if(qr>m) ans2=query_min(rt<<1|1,m+1,r,ql,qr);return min(ans1,ans2); }int main() {int n;sca(n);sum[0]=0;for(int i=1;i<=n;i++){sca(a[i]);sum[i]=sum[i-1]+a[i];}for(int i=1;i<=n;i++){while(!S.empty()&&a[S.top()]>=a[i])S.pop();if(S.size()==0)L[i]=0;else L[i]=S.top();S.push(i);}while(!S.empty())S.pop();for(int i=n;i>=1;i--){while(!S.empty()&&a[S.top()]>=a[i])S.pop();if(S.size()==0)R[i]=n;else R[i]=S.top()-1;S.push(i);}build(1,0,n);LL ans=-inf;for(int i=1;i<=n;i++){if(a[i]>=0){LL ans1=query_max(1,0,n,i,R[i]);LL ans2=query_min(1,0,n,L[i],i);ans=max(ans,a[i]*(ans1-ans2));}else{LL ans1=query_min(1,0,n,i,R[i]);LL ans2=query_max(1,0,n,L[i],i);ans=max(ans,a[i]*(ans1-ans2));}}cout<<ans<<endl; }Problem J?Distance on the tree
https://nanti.jisuanke.com/t/38229
題意:給你一棵樹,每條邊都有一個權值,m個詢問,問你從x到y的路徑上有多少條邊的值<=w。
題解:LCA
一邊dfs一邊建樹,每一個點的狀態是從它父親的狀態轉移過來的。那么兩個點之間的所有可能就是一個點到他們的lca+另一個點到他們的lca。注意存邊權的話,是要存在兒子節點上的。
?
Problem K?MORE XOR
https://nanti.jisuanke.com/t/38230
題解:規律
C++版本一
#include<bits/stdc++.h> #define ll long long #define pb push_back #define INF 0x3f3f3f3f #define FI first #define SE second #define MP make_pair #define PI pair<int,int> #define lson l,m,rt<<1,ls,rs #define rson m+1,r,rt<<1|1,ls,rs #define test printf("here!!!\n") using namespace std; const int mx=1e5+10; int n,m,p,q; int qz[4][4][mx]; int hz[4][4][mx]; int a[mx]; int main() {int t;scanf("%d",&t);while (t--){memset(qz,0,sizeof(qz));memset(hz,0,sizeof(hz));scanf("%d",&n);for (int i=1;i<=n;++i){scanf("%d",&a[i]);}for (int i=1;i<=n;++i){for (int j=0;j<4;++j){int id=(i-1)%4;int hgf=(1+j)%4;if (id==j){qz[1][j][i]=qz[1][j][i-1]^a[i];}else qz[1][j][i]=qz[1][j][i-1];if (id==j||id==hgf){qz[2][j][i]=qz[2][j][i-1]^a[i];}else qz[2][j][i]=qz[2][j][i-1];if (id==hgf){qz[3][j][i]=qz[3][j][i-1]^a[i];}else qz[3][j][i]=qz[3][j][i-1];}}for (int i=n;i>=1;--i){for (int j=0;j<4;++j){int id=(i-1)%4;int hgf=(1+j)%4;if (id==j){hz[1][j][i]=hz[1][j][i+1]^a[i];}else hz[1][j][i]=hz[1][j][i+1];if (id==j||id==hgf){hz[2][j][i]=hz[2][j][i+1]^a[i];}else hz[2][j][i]=hz[2][j][i+1];if (id==hgf){hz[3][j][i]=hz[3][j][i+1]^a[i];}else hz[3][j][i]=hz[3][j][i+1];}}scanf("%d",&q);int l,r;for (int i=1;i<=q;++i){scanf("%d%d",&l,&r);int dis=(r-l+1)%4;int cxk=(l-1)%4;if (dis!=0) printf("%d\n",qz[dis][cxk][n]^qz[dis][cxk][l-1]^hz[dis][cxk][r+1]);else printf("0\n");}} }C++版本二
題解:規律
打表代碼:
while(1){scanf("%d",&n);for(int l=1;l<=n;l++){for(int r=l;r<=n;r++){memset(vis,0,sizeof(vis));for(int l1=l;l1<=r;l1++){for(int r1=l1;r1<=r;r1++){for(int l2=l1;l2<=r1;l2++){for(int r2=l2;r2<=r1;r2++){for(int i=l2;i<=r2;i++){vis[i]=!vis[i];}}}}}cout<<l<<" "<<r<<endl;for(int i=1;i<=12;i++){cout<<vis[i];}cout<<endl;}}}1、可以發現當區間確定時,是否取用成一個固定的規律;
2、同長度的區間,取法相同;
3、對于一定的區間取法循環節長度為4,例如【1,9】循環節1000,整個區間取法100010001,并且區間長度循環節也為4,例如長度為1的區間和長度為5的區間取法循環節相同;
/* *@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]; int vis[N]; char str; int qz[4][4][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",&n);for(int i=1;i<=n;i++){scanf("%d",&a[i]);}memset(qz,0,sizeof(qz));for(int i=1;i<=n;i++){for(int j=0;j<4;j++){int pos=(i-1)%4;int dis=(j+1)%4;if(pos==j){qz[1][j][i]=qz[1][j][i-1]^a[i];}else{qz[1][j][i]=qz[1][j][i-1];}if(pos==j||dis==pos){qz[2][j][i]=qz[2][j][i-1]^a[i];}else{qz[2][j][i]=qz[2][j][i-1];}if(dis==pos){qz[3][j][i]=qz[3][j][i-1]^a[i];}else{qz[3][j][i]=qz[3][j][i-1];}}}scanf("%d",&m);while(m--){scanf("%d%d",&l,&r);int pos=(r-l+1)%4;int dis=(l-1)%4;int res=qz[pos][dis][r]^qz[pos][dis][l-1];cout<<res<<endl;}}#ifdef DEBUGprintf("Time cost : %lf s\n",(double)clock()/CLOCKS_PER_SEC); #endif//cout << "Hello world!" << endl;return 0; }C++版本三
Problem?L qiqi'tree
https://nanti.jisuanke.com/t/38231
Problem M?Subsequence
https://nanti.jisuanke.com/t/38232
題解:預處理+貪心
/* *@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[N],s[N]; int pos[N][130]; 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--){cin>>str+1;scanf("%d",&n);int len=strlen(str+1);for(int i=0;i<128;i++){pos[len][i]=len+1;}for(int i=len-1;i>=0;i--){for(int j=0;j<128;j++){pos[i][j]=pos[i+1][j];}pos[i][str[i+1]]=i+1;}while(n--){scanf("%s",s);int l=strlen(s);int id=pos[0][s[0]];int r=0;while(id<=len&&r<l){r++;id=pos[id][s[r]];}//cout<<l<<" "<<r<<endl;cout<<((r==l)?"YES":"NO")<<endl;}//}#ifdef DEBUGprintf("Time cost : %lf s\n",(double)clock()/CLOCKS_PER_SEC); #endif//cout << "Hello world!" << endl;return 0; }?
總結
以上是生活随笔為你收集整理的The Preliminary Contest for ICPC China Nanchang National Invitational的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 2019中山大学程序设计竞赛
- 下一篇: 浙江理工大学2019年4月赛