1. 程式人生 > >【EOJ Monthly 2018.12 - A,B,C】套題訓練,部分題解

【EOJ Monthly 2018.12 - A,B,C】套題訓練,部分題解

A.

題幹:

A. 仰望星空

單測試點時限: 2.0 秒

記憶體限制: 512 MB

你就這樣靜坐在草地上,離我稍遠的地方。
我用眼角瞅著你,你什麼話也別說。
語言是誤會的根源。
但是,每天,你可以坐得離我近一些……

你和她一起仰頭仰望著佈滿星辰的天空。你的星星對她而言只不過是眾星中的一顆。

她會喜歡仰望天際所有的繁星,他們都會是她的朋友。但你深信你不會是萬眾中一顆毫不起眼的星星。

於是你默默地記錄著每天你們仰望星空時的距離,你發現每天你們的距離或許減少、或許不變,但一定不會增加。

可是你們在一起仰望星空的日子太長了,長到你只記得你們第一天在星空下的距離。

今天,你們的距離是 A ;你們又在一起仰望星空了。你卻突然想知道一起仰望星空 N 天來,你們之間的距離之和。

由於你已經不記得每天的距離,只能依稀記起第一天的距離是 B ,所以你只想知道你們這麼多天來的距離之和有多少種不同的可能性。

輸入

輸入資料包含一行,包含三個整數 N,A,B (2≤N≤109,1≤A≤B≤109 ),分別表示你們一起仰望星空的天數、今天你們之間的距離以及第一天你們之間的距離。

輸出

輸出資料包含一行一個整數,表示不同可能和的個數。

樣例

Input

3 1 2

Output

2

提示

對於樣例有以下幾種不同的距離情況:{2,1,1},{2,2,1} ;他們的和分別是 4 和 5 ,所以有兩種不同的和。

解題報告:

  不算思維的思維題啊,,貪心出最大的可能取值和最小的可能取值就行了。

AC程式碼:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<queue>
#include<map>
#include<vector>
#include<set>
#include<string>
#include<cmath>
#include<cstring>
#define ll long long
#define pb push_back
#define pm make_pair
#define fi first
#define se second
using namespace std;
const int MAX = 2e5 + 5;
ll n,a,b;
int main()
{
	cin>>n>>a>>b;
	ll minn = a*(n-1) + b;
	ll maxx = a + b*(n-1);
	printf("%lld\n",maxx-minn+1);

	return 0 ;
 }

(不少人沒開longlong所以WA??)

 


B.

  好像是蒙特卡洛模擬,,據說隨機數也能過。。明天補補吧。。


C.

題幹:

C. 她的名字

單測試點時限: 4.0 秒

記憶體限制: 512 MB

“他走過一個又一個星球,
卻始終放不下對她的思念。“
”深情終究是一趟孤獨的旅程,
她是他永遠的牽絆。”

我們每個人心中都有一隻小狐狸。我們渴望被自己喜歡的人馴服。

愛情是彼此之間至為甜蜜的臣服。我們都是傻痴痴的小狐狸,徒具一副精明的外表。

就像你走到哪都掛念著她,想把她寫進自己的歌裡,成為你們共同的記憶。

你想從她全部由數字構成的名字裡取出其中的 N 個數字,維持原來的順序,組成結尾為數字 XY 的新詞。

你自然希望自己的歌能夠很長很長,歌詞的每一句都能飽含甜蜜。

所以你想知道,她的名字能夠組成多少個長度為 N 且結尾為數字 XY 的新詞(如果從她名字中取出的任意一個數字位置不同,兩個詞就被認為是不同的)。

輸入

第一行包含一個由數字構成的字串 S (1≤|S|≤2 000 )。

第二行包含一個整數 Q (1≤Q≤5⋅105 ),表示需要選擇的不同結尾數量。

接下來的 Q 行,每行包含了一個整數 N (1≤N≤5⋅105 ) 和兩個數字 XY ,用空格隔開,表示需要選擇的歌詞的長度和結尾。

輸出

對於每一個詢問,輸出一個整數,表示答案。

答案可能會很大,你只需要輸出對於 109+7 取模後的結果。

樣例

Input

312121
4
2 21
3 31
4 22
3 22

Output

3
0
1
2

提示

樣例中第一個詢問:312121, 312121, 312121.

第二個詢問:無。

第三個詢問:312121.

解題報告:

   就是個dp[i][j][k],,兩邊預處理,,第一遍出狀態的個數,第二遍出答案,然後O(1)輸出就行了。

AC程式碼:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<queue>
#include<map>
#include<vector>
#include<set>
#include<string>
#include<cmath>
#include<cstring>
#define ll long long
#define pb push_back
#define pm make_pair
#define fi first
#define se second
using namespace std;
const int MAX = 2e5 + 5;
const ll mod = 1e9 + 7;
int q;
char s[MAX];
ll dp[12][12][4005],qq[12][12],yong[12][12][4005];
ll C[2005][2005];
void init() {
	C[0][0]=1;
	for(int i=1; i<=2001; i++) {
		C[i][0]=1;
		for(int j=1; j<=i; j++) {
			C[i][j]=(C[i-1][j-1]+C[i-1][j])%mod;
		}
	}
}
int main()
{
	init();
	cin>>(s+1);
	int n = strlen(s+1);
	if(n == 1) {
		int q,len,x,y;
		scanf("%d",&q);
		while(q--) {
			scanf("%d",&len);
			scanf("%1d%1d",&x,&y);
			printf("0\n");
		} 
		return 0 ;
	}
	for(int i = 1; i<=n; i++) {
		for(int j = i+1; j<=n; j++) {
			dp[s[i]-'0'][s[j]-'0'][i-1]++;
			dp[s[i]-'0'][s[j]-'0'][i-1]%=mod;
			qq[s[i]-'0'][s[j]-'0'] = (qq[s[i]-'0'][s[j]-'0'] + 1) % mod;//以ij為尾的數有多少種. 
		}
	}
	for(int x = 0; x<=9; x++) {
		for(int y = 0; y<=9; y++) {
			for(int i = 0; i<=n; i++) {//記錄直接用 
				for(int j = i; j<=n; j++)
					yong[x][y][i] += (C[j][i] * dp[x][y][j])%mod;
			}
		}
	}
	cin>>q;
	int x,y,len;
	while(q--) {
		scanf("%d",&len);
		len-=2;
		scanf("%1d%1d",&x,&y);
		if(len+2 > n) {
			puts("0");continue;
		}
		if(len == 0) {
			printf("%lld\n",qq[x][y]%mod); continue;
		}
		if(len < 0) {
			puts("0");continue;
		}
		printf("%lld\n",yong[x][y][len]%mod);
		
	}
	return 0 ;
 }

注意N給到了1e5,,所以需要特判一波是否大於字串長度,如果大於了直接輸出0就行了,不然肯定RE啊,,

不過據說這題標解不是n^2*100的做法的。。改天再想想、、

這題WYZ大佬還有個別的做法,,從後往前 列舉每一個X,同時記錄Y的個數,然後輸出答案同時記錄,因為查詢次數過多,,肯定有重複查詢,所以類似記憶化搜尋那樣記錄答案,,貌似也過了。Orz


DEF不會,,其實E還可以做做的,,然後F是個SAM好像是,,目前也不會。

總之這場比賽寫題半小時掛機一個半小時,,題目跨度忒大了點。。兩題後就沒可做題了。。可能還是苔菜了吧。。