EOJ 2018 1 29新生訓練Week2

2021-08-15 09:43:22 字數 3915 閱讀 1283

總體來說不算好做……但是確實也不難。

給定正整數n,k,求f(

n,k)

=∑ni

=1ik

f (n

,k)=

∑i=1

ni

k,結果對19260817取模。

1 <= n <= 1e7, 0 <= k <= 1e9

時限0.698s(???)

上來用拉格朗日插值法直接wa。。正解其實比想象的簡單。先尤拉篩出素數,對素數用快速冪求出i^k存起來。然後對合數的i^k只要用素數的結果求就可以了。

#include

using

namespace

std;

typedef

long

long ll;

const

int p = 19260817;

const

int maxn = 1e7+5;

bool flag[maxn];

ll f[maxn], prime[maxn], n, k, cnt;

inline ll pow_mod(ll a, ll b)

return res;

}inline

void sieve()

for (int j = 0; j < cnt && i * prime[j] <= n; ++j)

}}int main()

給出乙個長度為 n 的整數數列 a,對於這個數列進行任意多操作。每次選擇乙個任意的整數,並將任意 p 個數字加上這個數字。輸出 yes 或 no,表示能否通過這種方法將這個數列中每個數字同時變成零。

1 ≤ p ≤ n ≤ 1e5, |ai| <= 1e6

結論題。顯然當n==p時只有所有數字相等時才是yes;n>p時,數字總和如果是p的倍數則yes。其實憑感覺可以想到:要把所有數字變成0,和必須是p的倍數。不過嚴格的證明則是將所有n>p的情況轉化為n==p+1的情況。

#include 

using

namespace

std;

int n, p, i, tmp, sum;

int main()

printf("%s\n", i == n ? "yes" : "no");

}else

printf("%s\n", sum % p ? "no" : "yes");

}return

0;}

給任意乙個大於 1 的正整數 n,輸出 n 可以分解成最少幾個質數(可以相同)的和。

2 ≤ n ≤ 1e15

據說是codeforces原題。

如果本身是質數那麼直接輸出1。

運用哥德**猜想,任何大於2的偶數可以被分解為兩個質數之和。也就是偶數輸出2。

如果n是奇合數但還可以被分解為兩個質數,那只可能是一奇一偶。偶質數只能是2,也就是說n-2必須是質數。

其他情況輸出3。

#include 

using

namespace

std;

typedef

long

long ll;

ll n;

inline

bool isprime(ll m)

int main()

給出 n 個正整數,問有多少種方法在這 n 個數字的中取其中一些數字,使得這些數字之和超過 k。若答案超過 20 000 000,輸出 -1。

1 ≤ n ≤ 1e4

1 ≤ ai ≤ 1e8

1 ≤ k ≤ 1e10

降序排序,預處理字首和,然後dfs+剪枝。

最優性剪枝:如果當前和已經大於k則剪枝,ans要加上2^(剩餘數字個數)——這一步還可以剪枝:由於2^25>2e7,所以一旦剩餘數字個數大於等於25也剪枝。

可行性剪枝:如果當前和加上後面所有數(用字首和)都不大於k那麼剪枝。

#include 

using

namespace

std;

typedef

long

long ll;

const

int maxn = 1e4+5;

int a[maxn], n, ans;

bool flag;

ll k, suma[maxn];

inline

void dfs(int dep, ll sum)

dfs(dep+1, sum + a[dep]);

dfs(dep+1, sum);

}int main()

給出整數數列 ,對整個數列進行盡可能少的次數操作,每次操作可以將數列中任意一項加 1 或者減 1,使得最終的數列 b1,b2,b3,…,bn 滿足對數列中的任一項 bi (i>=2),有 bi

=bi−

1+i bi=

bi−1

+i

。 求最少的操作次數。1 ≤ n ≤ 1e5,1 ≤ ai ≤ 1e10

設=,這題等價於求|c

1−x|

+|c2

−x|+

...+

|cn−

x|| c1

−x|+

|c2−

x|+.

..+|

cn−x

|的最小值。根據高中函式知識,x應該取cn的中位數。那麼我們構造出cn然後排下序取中間下標,這題就做完了……

#include 

using

namespace

std;

typedef

long

long ll;

const

int maxn = 1e5+5;

ll a[maxn], b[maxn], ans;

int n;

inline ll fun(ll mid)

int main()

sort(a+1, a+1+n);

printf("%lld\n", fun(a[(n+1)>>1]));

return

0;}

對於給定的數字串a1

,a2,

a3,…

,an a1,

a2,a

3,…,

an

,每次可以進行如下操作: 選擇乙個數 i (1 < i < n),將 ai

a

i變成 ai

+1+a

i−1−

aia i+

1+ai

−1−a

i。問在經過任意多次的操作後,該數列的數字總和最小為多少?

1 ≤ n ≤ 1e5,0 ≤ ai ≤ 1e10令c

i=ai

+1−a

i ci=

ai+1

−a

i,這樣c數列有n-1項。注意到對ai

a

i的操作等價於交換ci

c

i與ci

+1c i+

1,那麼通過將c公升序排序後反構造出的a數列就是總和最小的數列啦。

#include 

using

namespace

std;

typedef

long

long ll;

const

int maxn = 1e5+5;

ll a[maxn], c[maxn], sum;

int main()

printf("%lld\n", sum);

return

0;}

到今天為止,終於把以前寫的需要多一些深入思考的題目記錄完畢了。

新生訓練2

時間匆忙,先把自己 弄上明天考完再做詳細題解和補剩下的題 昨天組長在報告上說我題解認真,感到十分愧疚,來補題解,所以抓緊來補題解 a.b.c d eat candies 讀懂題很容易理解,先取最大的,然後如果最大的值大於另外兩個的和,則最大天數等於另外兩個的和,否則取另外兩個和與最大天數差值,除於2...

JXUST ECJTU新生訓練賽

a.此題由於字串的長度是10 5,所以利用o n 2 暴力來做的話,顯然是超時的,所以不採用這種方法,我們可以計算每個字元 出現的次數,而題目中 告訴pairs x,y and y,x should be considered different,所以組成的個數總和就是 每個字元出現的次數的乘積之和...

2021新生訓練題解02

a 思路 dp 由於每乙個點只能從該點的左側或上側到達,因此到達該點的最小花費一定在到達該點上側和左側之前產生,可得轉移方程 dp i j min dp i 1 j dp i j 1 注意特判i 1 0和 j 1 0 的情況 標程 b 思路 數學幾何 沿著柱面向上走,可將柱面展開,變成乙個矩形,兩點...