【CF 1188 A1,B,C】Add on a Tree // Count Pairs // Array Beauty
傳送門
這些天風也溫柔,題也溫柔
開車啦!
文章目錄
- A1:Add on a Tree
- 題意翻譯
- 題解
- 證明
- 代碼實現(xiàn)
- B:Count Pairs
- 題意翻譯
- 題解
- 代碼實現(xiàn)
- C:Array Beauty
- 題目描述
- 題解
- 代碼實現(xiàn)
A1:Add on a Tree
題意翻譯
給定一棵樹,樹上的邊權初始為0,你可以在任意兩個葉子之間的簡單路徑上的邊上加上一個權值實數(shù)x。問:能否在有限次數(shù)的操作內,得到邊權任意組合的樹。
題目描述
Note that this is the first problem of the two similar problems. You can hack this problem only if you solve both problems.
You are given a tree with n n nodes. In the beginning, 0 is written on all edges. In one operation, you can choose any 2 distinct leaves u , v and any real number x and add x x to values written on all edges on the simple path between u and v .
For example, on the picture below you can see the result of applying two operations to the graph: adding 2 on the path from 7 to 6 , and then adding ?0.5 on the path from 4 to 5 .
Is it true that for any configuration of real numbers written on edges, we can achieve it with a finite number of operations?
Leaf is a node of a tree of degree 1 . Simple path is a path that doesn’t contain any node twice.
輸入格式
The first line contains a single integer n n ( 2≤n≤10^5) — the number of nodes.
Each of the next n?1 lines contains two integers u and v (1≤u,v≤n , u≠v ), meaning that there is an edge between nodes u and v. It is guaranteed that these edges form a tree.
輸出格式
If there is a configuration of real numbers written on edges of the tree that we can’t achieve by performing the operations, output “NO”.
Otherwise, output “YES”.
You can print each letter in any case (upper or lower).
輸入輸出樣例
輸入
2
1 2
輸出
YES
輸入
3
1 2
2 3
輸出
NO
輸入
5
1 2
1 3
1 4
2 5
輸出
NO
輸入
6
1 2
1 3
1 4
2 5
2 6
輸出
YES
說明/提示
In the first example, we can add any real x x to the value written on the only edge (1, 2)
In the second example, one of configurations that we can’t reach is 0 0 written on (1, 2) and 1written on(2,3) .
Below you can see graphs from examples 3 , 4 :
題解
首先看這個題目大意,你可能會被嚇到,這題這么難?但是你想這可是CF第一題啊!
那么一定是水題,而這道題就是一個神仙結論題!!
如果有一個點只連了兩條邊,就一定是輸出NO,沒有就輸出YES
我當時知道后一臉懵逼
證明
后來拿著數(shù)據(jù)慢慢推又發(fā)現(xiàn)自己腦子不行,我們還是假設未知數(shù)來推吧!
首先如果這是一條單鏈,我們也能將它變?yōu)橐粋€二叉樹
接下來的討論情況是在不是單鏈的前提下進行的
因為是要兩個葉子節(jié)點彼此間的路徑全都加上或減去x,一定會經過它們的lca
所以我們要以lca來進行討論
也可以這么理解,把它們的lca和lca的子樹單獨摳出來考慮,讓lca成為根節(jié)點
設i點連的邊數(shù)為edge
1)edge = 1,意味著i點是葉子節(jié)點,不考慮,特殊情況輸出YES,如樣例1
2)edge = 2,如圖:
如果這兩條邊的邊權要求不一樣,就無法完成
因為加權或減權都要選擇兩個不同的葉子節(jié)點,
而lca只有這兩個葉子節(jié)點,也就是說這兩個點的邊只能一起加一起減
自然也就組合不出不同的邊權了
3)edge=3,如圖:
因為要組合成任意邊權,所以3,5,7與5,3,7本質上木有區(qū)別
所以我們就假設要滿足的邊權i<=j<=k
(1)i+j=k,直接i,k和j,k就能完成
(2)i+j<k,首先一三點都加上i和二三點j,k都加上j此時第三個點還差k-i-j
如果差的是奇數(shù),
那么第一二個點就分別與他組合(k-i-j)*1.0 / 2,
再一二個點組合減去(k-i-j)*1.0/ 2即可滿足
如果差的是偶數(shù)
那么第一二個點就分別與他組合(k-i-j)/ 2,
再一二個點組合減去(k-i-j)/ 2也可滿足
PS:加減實數(shù),即有理數(shù),所以也可以加減無限循環(huán)或有限小數(shù)
(3)i+j>k,與情況二差不多,
首先一三點都加上i和二三點j,k都加上j此時第三個點多了k-i-j
如果多的是奇數(shù),
那么第一二個點就分別與他組合減掉(k-i-j)*1.0 / 2,
再一二個點組合加上(k-i-j)*1.0/ 2即可滿足
如果差的是偶數(shù)
那么第一二個點就分別與他組合減掉(k-i-j)/ 2,
再一二個點組合加上(k-i-j)/ 2也可滿足
綜上當葉子節(jié)點個數(shù)為3時,一定能湊出任何邊權
4)當edge=4時,
(1)i+j+k=l,坑定可以滿足,不多說
(2)i+j+k<l,首先i,l;j,l;k,l分別組合先讓l滿足,就不用再考慮l了
于是就轉換成了讓i,j,k三個滿足邊權,我們已經證明過了三個的時候一定成立
所以這個情況也一定成立
(3)i+j+k>l,與情況(2)一樣,先讓l滿足后就不考慮l轉換成三個葉子節(jié)點的情況
所以此情況也一定成立
5)以此類推edge>3的時候,就依次讓edge,edge-1,edge-2滿足要求,不再考慮,
最后都能轉換成edge=3的情況,
所以edge>3也是一定可以組合出任意邊權
所以綜上所述,只有edge=2的時候會組合不出任意邊權,輸出NO否則YES
好了證明完了,這道題發(fā)揮了它該有的價值,我也心安理得了
代碼實現(xiàn)
這是個水題,代碼量自然也就不會那么ex,主要是寡人剛開始沒把這個英文題意搞懂
#include <cstdio> #define MAXN 100005 int n; int du[MAXN]; int main() {scanf ( "%d", &n );for ( int i = 1;i < n;i ++ ) {int u, v;scanf ( "%d %d", &u, &v );du[u] ++;du[v] ++;}for ( int i = 1;i <= n;i ++ )if ( du[i] == 2 )return ! printf ( "NO" );printf ( "YES" );return 0; }B:Count Pairs
題意翻譯
給定一個質數(shù) p , 一個長度為 n 的序列 a1,a2,…,an和一個整數(shù) k.
求所有數(shù)對 (i, j) (1≤i,j≤n) 中滿足 (ai + aj) * (ai^2 + aj^2 ) ≡k mod p.的個數(shù).
題目描述
You are given a prime number p , n ,integers a1, a2…an and an integer k .
Find the number of pairs of indexes (i, j)(1≤i<j≤n) for which (ai+aj)(ai^2 + aj^2) ≡k mod p .
輸入格式
The first line contains integers n, p, k ( 2≤n≤3?10^5, 2≤p≤10^9,0≤k≤p?1 ). p is guaranteed to be prime.
The second line contains n integers a1, a2,…,a n,0≤ai≤p?1 ). It is guaranteed that all elements are different.
輸出格式
Output a single integer — answer to the problem.
輸入輸出樣例
輸入
3 3 0
0 1 2
輸出
1
輸入
6 7 2
1 2 3 4 5 6
輸出
3
說明/提示
In the first example:
(0+1)(0^2 + 1^2) = 1 ≡ 1 mod 3 .
(0+2)(0^2 + 2^2) = 8 ≡ 2 mod 3 .
(1+2)(1^2 + 2^2) = 15 ≡ 0 mod 3 .
So only 1 pair satisfies the condition.
In the second example, there are 3 3 such pairs: (1, 5) , (2, 3), (4, 6) .
題解
首先要知道,n的范圍很大,這就告訴我們,時間復雜度控制在O(n),
盡管這個時間開的是4s,n^2也不是我們想要的好代碼!
那么我們就要式子進行變換,而且看到同余就知道是數(shù)論,也就要用到數(shù)學
(ai + aj) * (ai^2 + aj^2 ) ≡k mod p
因為p是質數(shù)所以左右兩邊同時乘以(ai-aj)等式仍然成立
即(ai+aj)(ai-aj)(ai^2 + aj^2) %p ≡ k(ai-aj)%p
即(ai^2 - aj^2) (ai^ + aj^2) % p ≡ k(ai-aj) %p
即(ai^4 - aj^4)%p ≡(aik - ajk) %p
移向即:
(ai^4-aik) %p ≡ (aj^ajk)% p
我們設f(x)表示(ax^4-axk) %p,k,p都是一定的
所以我們可以在輸入ai的時候就處理出每一個f(x)
之后我們只需要找到有多少個與f(x)同余的即可,(i,j)與(j,i)算一個!!
我們不能用兩重循環(huán)去找因為會TLE所以我們可以sort一下,保持它的單調性,這樣就可以在一重循環(huán)內進行答案計算
答案每次應該加多少呢?我們來想如果有n個同余的數(shù)
那么第一個數(shù)與后面的組合個數(shù)為n-1,第二個數(shù)與后面的組合個數(shù)為n-2,以此類推
最后一個后面沒數(shù),組合數(shù)為0
就可以列出公式0+1+2+…+n-2+n-1也就是我們的等差數(shù)列求和公式
好了,話不多說,屁不多放,上馬!
代碼實現(xiàn)
終于本仙女沒有在mod上懷疑人生了,我很欣慰
#include <cmath> #include <cstdio> #include <algorithm> using namespace std; #define MAXN 300005 #define LL long long int n, p; LL k, t; LL result; LL f[MAXN]; int main() {scanf ( "%d %d %lld", &n, &p, &k );for ( int i = 1;i <= n;i ++ ) {scanf ( "%lld", &t );//f[i] = ( ( LL ) pow ( t, 4 ) % p - ( t * k ) % p + p ) % p;//不要這么寫,炸不炸longlong全靠運氣,pow不會炸duoble會炸longlong//相同代碼在luogu交有時會AC有時連樣例數(shù)據(jù)都過不了//真玄學LL ip = t * t % p * t % p * t % p;f[i] = ( ip % p - ( t * k ) % p + p ) % p;}sort ( f + 1, f + n + 1 );LL cnt = 1;for ( int i = 2;i <= n;i ++ ) {if ( f[i] == f[i - 1] )cnt ++;else {result = ( result + ( ( cnt - 1 ) * cnt / 2 ) % p ) % p;cnt = 1;}}if ( cnt > 1 )result = ( result + ( ( cnt - 1 ) * cnt / 2 ) % p ) % p;printf ( "%lld", result );return 0; }C:Array Beauty
題目描述
我們稱序列b 1 ?,b 2 ? ,…,b n ?( n > 1 ) 的美麗值為min ? ∣b i ? ?b j ?∣(1≤i<j≤n)
給你一個序列a 1 ? ,a 2 ? ,…a n ?和一個數(shù)字k,請您計算出長度為k的序列a的所有子序列的美麗值之和,由于這個值可能很大,所以輸出是模998244353。
如果可以通過刪除幾個(可能為零或全部)元素從B中獲得A,則序列A是數(shù)組B的子序列。
輸入輸出格式
輸入格式:
第一行包含整數(shù) ( 2≤k≤n≤1000 )。
第二行包含n個整數(shù) a 1 ? ,a 2 ? ,…,a n ? ( 0≤a i ? ≤10^ 5 )。
輸出格式:
輸出一個整數(shù) — 長度為k的序列a的所有子序列的美麗值之和 , 由于這個值可能很大,所以輸出是模998244353 。
題目描述
Let’s call beauty of an array b1, b2,…,bn( n > 1) —(1≤i<j≤n) min∣bi?bj∣ .
You’re given an array a1, a2,…an and a number k . Calculate the sum of beauty over all subsequences of the array of length exactly k . As this number can be very large, output it modulo 998244353 .
A sequence a is a subsequence of an array b if a can be obtained from b by deletion of several (possibly, zero or all) elements.
輸入格式
The first line contains integers n, k ( 2≤k≤n≤1000 ).
The second line contains n integers a1, a2,…,an( 0≤a i ≤10^5 ).
輸出格式
Output one integer — the sum of beauty over all subsequences of the array of length exactly k . As this number can be very large, output it modulo 998244353 .
輸入輸出樣例
輸入
4 3
1 7 3 5
輸出
8
輸入
5 5
1 10 100 1000 10000
輸出
9
說明/提示
In the first example, there are 4 subsequences of length 3 — [1, 7, 3] [1, 3, 5] , [7, 3, 5] , [1, 7, 5] , each of which has beauty 2 , so answer is 8 .
In the second example, there is only one subsequence of length 5 — the whole array, which has the beauty equal to |10-1| = 9.
題解
對于給定的數(shù)組,由于不是有序的,所有相連的值最小,而子序列也不要求是連續(xù)的,肯定要先進行排序(從小到大),得到一個有序的數(shù)組,
這樣得到的子序列也是有序的。
假設一個序列的最小值為x,即a[i]?a[i?1]≥x,即所有的相連數(shù)字之差都大于等于x。
如果一個我們要找序列的值為1的個數(shù)為N,那么和就是1×N,
如果序列的的值為2的個數(shù)為M,那么和就是2×M,
但是在N個序列中肯定包含值為2的M個序列,
那么總的和就是N+2×M?M×1=N+M(M×1就是在值為1中重復的個數(shù))(容斥思想),
這樣我們就可以發(fā)現(xiàn)我們從小到大連續(xù) 的序列的值,就是將他們的序列個數(shù)相加。
用動態(tài)規(guī)劃DP的思想
dp[i][len]
其中:i表示第i個數(shù)組加入序列,len表示此時序列的長度為len,
那么dp[i][len] 就表示第i個數(shù)字加入,長度為len的子序列的個數(shù)。
假設此時序列的最小值為x
那么對于第i個數(shù)字,如果它不加入序列,那么此時就可以表示為
dp[i][len]+=dp[i?1][len]
如果加入序列,那么我們需要找到一個位置讓a[i]?a[j]≥x,1≤j≤last
dp[i][len]+=dp[last][len?1]
綜上:
dp[i][len]=dp[i?1][len]+dp[last][len?1]
最后對于序列最小值為x,得到的序列個數(shù)就是dp[n][k],由于這個值和x有關,記為f(x)
那么最終的結果就是
==result=∑x=(1,10^5/(k-1))*f(x) ==
所以這道題就是一個簡單 dp
代碼實現(xiàn)
這里解釋兩個地方
1)result求解的for循環(huán)的取值范圍
首先i模擬的是美麗值,那么有長度為k的序列,為了維護序列中最小的美麗值為i
最大的一個數(shù)應該是i*(k-1),因為i占第一個,所以是乘以k-1,
而且每一個a都不能超過100000,所以條件是這個序列的最后一個的值<=MAX
2)為什么last是與i滿足條件的最接近與i的下標
dp[i][j]是i進入序列和i不進入序列的情況數(shù)總和,
那么dp[i-1][j-1]也包含了i-1進入序列和i-1不進入序列情況的總和,
所以如果是加上dp[i-1][j-1]
也包含了i直接略過last接在前面任何一個與i滿足美麗值要求的方案總數(shù)
如果不這樣寫,就要再用一重循環(huán)去模擬前面所有與i組合合法的j再累加
#include <cstdio> #include <algorithm> using namespace std; #define mod 998244353 #define LL long long #define MAXN 1005 #define MAX 100000 int n, k; int a[MAXN]; LL dp[MAXN][MAXN]; LL result;int beauty ( int val ) {dp[0][0] = 1;int last = 0;for ( int i = 1;i <= n;i ++ ) {while ( a[i] - a[last + 1] >= val ) last ++;dp[i][0] = dp[i - 1][0];for ( int j = 1;j <= k;j ++ )dp[i][j] = ( dp[i - 1][j] + dp[last][j - 1] ) % mod;}return dp[n][k]; }int main() {scanf ( "%d %d", &n, &k );;for ( int i = 1;i <= n;i ++ )scanf ( "%d", &a[i] );sort ( a + 1, a + n + 1 );for ( int i = 1;i * ( k - 1 ) <= MAX;i ++ )result = ( result + beauty ( i ) ) % mod;printf ( "%lld", result );return 0; }好了,你左丟一個表情包,右丟一個表情包,閃現(xiàn)收人頭!
今天的節(jié)目到此結束,有任何問題歡迎留言,也可以留下你的想法和思路
幫助博主完善這份博客小朋友。我們下期再見哦~~
總結
以上是生活随笔為你收集整理的【CF 1188 A1,B,C】Add on a Tree // Count Pairs // Array Beauty的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 恐怖庄园的秘密攻略,游戏通关图文教程
- 下一篇: 内存卡检测工具怎么用