Codeforces Round #722 (Div. 2)
题目:https://codeforc.es/contest/1529
A. Eshag Loves Big Arrays
题意:略
题解:发现随便取两个不同的数,一定可以删掉大的那个数。所以最后留下的肯定是最小的所有数。

#include<iostream> #include<algorithm> #include<vector> #include<stack> #include<map> #include<cmath> #include<cstring> using namespace std; const int mx=2e5+10; const int inf=1<<30; typedef long long ll; void solve(){ ll t; scanf("%lld", &t); for(ll lp=1;lp<=t;lp++){ ll num, v; scanf("%lld", &num); map<ll,ll>mp; for(ll i=1;i<=num;i++){ scanf("%lld", &v); mp[v]++; } map<ll,ll>::iterator it=mp.begin(); printf("%lld\n", num-(it->second)); } } int main(){ solve(); return 0; }
B. Sifid and Strange Subsequences
题意:求最长子串,让任意两数之差的绝对值大于等于最大数。
题解:
首先最多只有一个正数。假如有两个正数,它俩绝对值之差肯定小于大的数。
所以最优搭配是:所有的负数+1个正数。
但是要判定一下是否有可能两数之差绝对值小于这个正数。(所以要选最小的正数 然后判断是否矛盾。矛盾就去掉正数

#include<iostream> #include<algorithm> #include<vector> #include<stack> #include<map> #include<cmath> #include<cstring> using namespace std; const int mx=1e5+10; typedef long long ll; const ll inf=3e9+10; ll t, num, v[mx]; void solve(){ scanf("%lld", &t); for(ll lp=1;lp<=t;lp++){ scanf("%lld", &num); for(ll i=1;i<=num;i++)scanf("%lld", &v[i]); sort(v+1, v+1+num); ll gs=0, min_dif=inf; ll i=1; ll bef=-inf; while(i<=num && v[i]<=0){ gs++; min_dif=min(min_dif,v[i]-bef); bef=v[i]; i++; } if(i<=num){ min_dif=min(min_dif, v[i]-bef); } if(i<=num && v[i]<=min_dif){ gs++; } printf("%lld\n", gs); } } int main(){ solve(); return 0; }
C. Parsa's Humongous Tree
题意:略
题解:树形dp
参考:https://www.cnblogs.com/wanshu/p/14807034.html#_lab2_2_1
我现在还是有点晕晕的为啥取边界值最优。。

#include<iostream> #include<algorithm> #include<vector> #include<stack> #include<map> #include<cmath> #include<cstring> using namespace std; const int mx=1e5+10; typedef long long ll; const ll inf=3e9+10; ll t, n, dp[mx][2];//dp[i][0]代表i号点取l的情况 1代表取r的情况 ll l[mx], r[mx]; struct edge{ ll v, nex; }e[mx<<1]; ll head[mx], tot; bool vis[mx]; void add(ll u, ll v){ tot++; e[tot].v=v;e[tot].nex=head[u]; head[u]=tot; } void work(ll c){//dp vis[c]=true; for(ll i=head[c];i;i=e[i].nex){ ll v=e[i].v; if(vis[v]==true)continue; work(v); dp[c][0]+=max(dp[v][0]+abs(l[c]-l[v]), dp[v][1]+abs(l[c]-r[v])); dp[c][1]+=max(dp[v][0]+abs(r[c]-l[v]), dp[v][1]+abs(r[c]-r[v])); } } void solve(){ scanf("%lld", &t); for(ll lp=1;lp<=t;lp++){ tot=0; for(ll i=1;i<=n;i++){ head[i]=dp[i][0]=dp[i][1]=0; vis[i]=false; } scanf("%lld", &n); for(ll i=1;i<=n;i++){ scanf("%lld %lld", &l[i], &r[i]); } for(ll i=1;i<=n-1;i++){ ll u, v; scanf("%lld %lld", &u, &v); add(u, v); add(v, u); } work(1); printf("%lld\n", max(dp[1][0], dp[1][1])); } } int main(){ solve(); return 0; }
D. Kavi on Pairing Duty
题意:略。
题解:
以n等于3为例。一共6个点。
然后考虑1号点和5、6相连的可能性。【为什么只考虑5、6之后说】
1和6连,那么2345都空出来了,2345的可能性就是n=2的可能性,答案为3。
1和5连,6只能和2连,那么34空出来了,可能性是n=1的可能性,答案为1。
最后考虑1和2,3,4的连法。【这些情况下 只能是所有都大小相同】
12情况,剩下的也都是相邻相邻。答案+1
13情况没有可能性(可以试着画一下。
14情况,彼此交叉。答案+1。
所以最后答案为3+1+1+1=6。
然后以n=4为例来看看。
考虑1号点和6、7、8相连可能性,对应答案为n=1、2、3的答案,为1+3+6=10。
然后考虑1和2,3,4,5相连可能性。
此时1和2、3、5都可以构成答案。所以答案+3。最后答案为13。
对于求n的答案
第一步:算对应答案为n=1、2、3。。。n-1的答案,这个可以用一个变量tot来记录。每次算一个n的时候就把对应的答案加上去。用tot来记录到n-1为止的答案和。
第二步:算1和2、3、4。。。。n可以构成答案的数量 这一步怎么算↓
为什么n=4的情况可以和2、3、5构成答案呢?
我们来看 相同大小交叉的最小情况
一个不交叉:2个点。
两个交叉:4个点。
三个交叉:6个点。
。。。
以此类推,所以只要2n是2、4、6.。。。2n的倍数。答案就会对应+1。
上面的内容可以转化为只要n是1、2、3。。。n的倍数,答案就会+1。
这里可以对n质因数分解,将上面的内容转化为,质因数可以构造多少个不同的数,答案就对应加多少数。
综上完成了所有内容。可以算了。

#include<iostream> #include<algorithm> #include<vector> #include<stack> #include<map> #include<cmath> #include<cstring> using namespace std; //const int mx=1e2+10; const int mx=1e6+10; const int inf=1<<30; typedef long long ll; const ll mod=998244353; ll two[mx]; ll prime[mx], tot; bool isp[mx]; ll f[mx]; ll fenjie(ll v){ ll ans=1; for(ll j=1;j<=tot;j++){ ll i=prime[j]; ll gs=0; if(i*i>v)break; if(v%i==0){ while(v%i==0){ v/=i; gs++; } ans*=(gs+1); ans%=mod; } } if(v!=1) { ans*=2; ans%=mod; } return ans;//多少种不同的数 } void init(){ isp[1]=true; for(ll i=2;i<mx;i++){ if(isp[i]==false)prime[++tot]=i; for(ll j=1;j<=tot;j++){ if(i*prime[j]>mx)break; isp[i*prime[j]]=true; if(i%prime[j]==0)break; } } } void init2(){ f[1]=1; ll curr_tot=1;//记录之前的答案综合 for(ll i=2;i<mx;i++){ f[i]=curr_tot; f[i]+=fenjie(i); f[i]%=mod; curr_tot+=f[i];//f[1]+f[2]+...+f[i]; curr_tot%=mod; } } void solve(){ init(); init2(); ll v; scanf("%lld", &v); printf("%lld\n", f[v]); } int main(){ solve(); return 0; }