The 14th Jilin Provincial Collegiate Programming Contest
阿新 • • 發佈:2022-03-06
The 14th Jilin Provincial Collegiate Programming Contest
目錄Problem A. Chord
Problem B. Problem Select
題解
簽到題,sscanf
從字串中讀入數字,排個序取前k
個。
程式碼
點選檢視程式碼
#include <bits/stdc++.h> #define rep(i, l, r) for (int i = l, iss = r; i <= iss; ++i) #define per(i, l, r) for (int i = r, iss = l; i >= iss; --i) #define pb emplace_back #define endl '\n' typedef long long ll; using namespace std; const int N = 1050; int main() { int tc; int n, m, k, t, in; char s[N]; vector<int> ans; for (scanf("%d", &tc); tc; --tc) { scanf("%d%d", &n, &k); rep(i, 1, n) { scanf("%s", s); m = strlen(s); rep(i, 0, m - 1) if (s[i] == '/') in = i; sscanf(s + in + 1, "%d", &t); ans.push_back(t); } sort(ans.begin(), ans.end()); rep(i, 0, k - 1) printf(i + 1 == k ? "%d\n" : "%d ", ans[i]); ans.clear(); } return 0; } /* 2 3 2 http://acm.hit.edu.cn/problemset/1003 http://acm.hit.edu.cn/problemset/1002 http://acm.hit.edu.cn/problemset/1001 4 1 http://acm.hit.edu.cn/problemset/1001 http://acm.hit.edu.cn/problemset/2001 http://acm.hit.edu.cn/problemset/3001 http://acm.hit.edu.cn/problemset/501 */
Problem C. String Game
題解
求一個串在另一個串中作為子串的出現次數
記 a[1:n]
為母串, b[1:m]
為子串;
設 f[i][j]
= k
: b[1:j]在a[1:i]中作為子串 且 a[i]=b[j] 出現的次數, 有轉移方程$ f[i][j]= \Sigma_{x=1}^{i-1}{f[x][j-1]}$
程式碼
點選檢視程式碼
#include<bits/stdc++.h> #define rep(i,l,r) for(int i=l,iss=r;i<=iss;++i) #define per(i,l,r) for(int i=r,iss=l;i>=iss;--i) #define pb emplace_back #define endl '\n' typedef long long ll; using namespace std; const int N=5050,M=1050,P=1e9+7; int n,m; char a[N],b[M]; ll f[N]; int main () { while(scanf("%s%s",a+1,b+1)!=EOF) { n=strlen(a+1),m=strlen(b+1); rep(i,1,n)f[i]=(a[i]==b[1]?1:0); rep(j,2,m) { ll prefix_sum=0; rep(i,1,n)prefix_sum+=f[i]; per(i,1,n) { prefix_sum-=f[i]; if(a[i]==b[j])f[i]=prefix_sum%P; else f[i]=0; } } ll ans=0; rep(i,1,n)ans+=f[i]; printf("%lld\n",ans%P); } return 0; } /* eeettt et eeettt te */
Problem D. Trie
Problem E. Shorten the Array
題解
結論題
什麼情況下會是1?: \(\exist s[i],s.t.\ s[i]\ \%\ min_x{s[x]}!=0\)
其它情況: \(ans=cnt(min_x{s[x]})+1>>1\)
程式碼
點選檢視程式碼
#include <bits/stdc++.h>
#define rep(i, l, r) for (int i = l, iss = r; i <= iss; ++i)
#define per(i, l, r) for (int i = r, iss = l; i >= iss; --i)
#define pb emplace_back
#define endl '\n'
typedef long long ll;
using namespace std;
const int N = 1e6 + 500;
int n, a[N];
int main()
{
int tc, ele, cnt;
bool flag;
for (scanf("%d", &tc); tc; --tc)
{
scanf("%d", &n);
rep(i, 1, n) scanf("%d", a + i);
ele = a[1], flag = false;
rep(i, 1, n) if (a[i] < ele) ele = a[i];
rep(i, 1, n) if (a[i] % ele != 0)
{
flag = true;
break;
}
if (flag)
{
printf("1\n");
}
else
{
cnt = 0;
rep(i, 1, n) if (a[i] == ele) cnt++;
printf("%d\n", cnt + 1 >> 1);
}
}
return 0;
}
Problem F. Queue
題解
可以是一道較難的題目, 動態逆序對可持久化線段樹可做, 出題人仁慈地放過了暴力;
考察交換兩個數字對逆序對數量的貢獻, 僅有 \(p_1<i<p_2, s[i] \in \left[s[p_1],s[p_2]\right]\) 中的元素會產生貢獻;
程式碼
點選檢視程式碼
#include <bits/stdc++.h>
#define rep(i, l, r) for (int i = l, iss = r; i <= iss; ++i)
#define per(i, l, r) for (int i = r, iss = l; i >= iss; --i)
#define pb emplace_back
#define endl '\n'
typedef long long ll;
using namespace std;
const int N = 1e5 + 500;
int n, s[N], m;
ll ori, ans;
struct BIT
{
#define Low_Bit(x) (x & (-x))
private:
int ran, bit[N];
public:
BIT(int ran) : ran(ran)
{
memset(bit, 0, sizeof(bit));
}
void add(int p, int x)
{
for (; p <= ran; p += Low_Bit(p))
bit[p] += x;
}
int sum(int p)
{
int rec = 0;
for (; p > 0; p -= Low_Bit(p))
rec += bit[p];
return rec;
}
#undef Low_Bit
};
void Init();
void Get_inversions();
void Process();
int main()
{
int tc;
for (scanf("%d", &tc); tc; --tc)
{
Init();
Get_inversions();
Process();
printf("%lld\n", ans);
}
return 0;
}
void Process()
{
scanf("%d", &m);
int l, r,f,lv,rv, cnt;
rep(i,1,m)
{
scanf("%d%d", &l, &r);
if (s[l] == s[r])
continue;
cnt = 1;
if (s[l] < s[r])f=1,lv=s[l],rv=s[r];
else f=-1,lv=s[r],rv=s[l];
rep(j,l+1,r-1)
{
if (s[j] >= lv && s[j] <= rv)cnt++;
if (s[j] > lv && s[j] < rv)cnt++;
}
ori=ori+f*cnt;
if(ori<ans)ans=ori;
swap(s[l], s[r]);
}
}
void Init()
{
n = m = 0;
ori = ans = 0ll;
memset(s, 0, sizeof(s));
return;
}
void Get_inversions()
{
scanf("%d", &n);
rep(i, 1, n) scanf("%d", s + i);
rep(i, 1, n)++ s[i];
int max_s = s[1];
rep(i, 1, n) if (s[i] > max_s) max_s = s[i];
BIT *bit = new BIT(max_s);
per(i, 1, n)
{
ori += bit->sum(s[i] - 1);
bit->add(s[i], 1);
}
ans = ori;
delete bit;
}
Problem G. Matrix
題解
當橫縱座標的乘積為奇數時, $ a(i,j)=1 $ ;
即橫縱座標值應分別為奇數;
$ans= \left\lfloor \sqrt{n} \right\rfloor* \left\lfloor \sqrt{m} \right\rfloor $
Problem H. Curious
題解
莫比烏斯反演 unfinished