傳送門:點我c++
題目很棒,感謝出題驗題的大佬們。數組
細節坑很多,是好事。ide
仍是很菜,繼續加油!函數
B:學習
描述測試
桃子這幾天在收集記念幣,總共最多隻有N種不一樣的記念幣,他已經收集了K種不一樣的記念幣。這不,桃子的生日快到了,他的M個小夥伴們決定送他記念幣,如何送給桃子呢?他們都贊成了以下三個規則:
spa
1. 每一個人送的記念幣與其餘人的都同樣多;code
2. 送給桃子的任意兩枚記念幣種類均不一樣; blog
3. 桃子從小夥伴那獲得至少L枚新的。遞歸
但他的小夥伴們不知道桃子收集了哪些記念幣。他們想盡可能少花錢,因此他們想購買知足規則的最少數量的記念幣。
輸入
第一行一個整數T(≤100),表明有T組數據。
對於每組數據,包含一行爲四個整數N, M, K, L(1≤K≤N≤1018,1≤M,L≤1018),表明有N種不一樣的記念幣,M個小夥伴,桃子原本有K種不一樣的記念幣,最後桃子手上至少有L枚新的記念幣。
輸出
輸出桃子的一個小夥伴贈送的最少數量的記念幣。若是不可能同時知足三個條件輸出-1。
樣例輸入
2
20 15 2 3
10 11 2 4
樣例輸出
1
-1
提示
第一組數據:桃子的小夥伴每人送一枚記念幣,由於桃子原來有2種記念幣,小夥伴總共送15枚,必定有至少13枚是新的,知足題目要求且最少。
第二組數據:總共有10種不一樣的記念幣,而桃子的小夥伴有11個,不能知足條件2。
思路:
首先,提示告訴咱們若是M>N是直接輸出-1。
很明顯能夠看出K+L是要達到的個數,若是K+L > M,也是能夠直接輸出-1的,由於達不到。
最後直接判斷每一個人送知足條件的個數,會不會超過N便可。具體看代碼有註釋
代碼:
#include<bits/stdc++.h> using namespace std; #define LL long long #define INF 2000000000 #define eps 1e-8 #define pi 3.141592653589793 const LL mod = 1e9+7; int main() { int _; for(scanf("%d",&_);_--;){ LL n,m,k,l; scanf("%I64d%I64d%I64d%I64d",&n,&m,&k,&l); if(m > n){ puts("-1");continue; } LL sum = k+l; if(sum > n){ puts("-1");continue; } LL ans = (sum%m == 0)?sum/m:sum/m+1;//每一個人要送的個數,保證能夠知足K+L if(ans * m > n){//若是每一個人送的總數超過了N,根據蜂巢原理一定會重複。因此不行 puts("-1");continue; } else{ printf("%I64d\n",ans); } } } /* 2 100 6 2 98 */
C
描述
taozi喜歡數學,可是遇到數學題就頭疼,zdragon爲了讓你們高興高興,給taozi出了道難題:
S=∑qi (1≤i≤n),因爲答案可能會很大,答案對p取模。
輸入
輸入第一行爲測試樣例組數T(1≤T≤100)。
對於每組數據第一行包含三個正整數n,q,p(1≤n,q,p≤109)。
輸出
對於每組數據,輸出一個S對p取模的值。
樣例輸入
2
3 2 100
4 511 520
樣例輸出
14
184
提示
對於第一個樣例,21+22+23=14,對100取模,答案爲14。
思路:
S=∑qi (1≤i≤n),這玩意首先是個等比數列求和。而後取模,很容易想到套等比數列求和公式,逆元,取模。然而會出錯。。由於可能在模數的意義下可能沒有逆元。
其實是等比數列二分求和處理這玩意(最近寫過同樣的題目因此知道怎麼作)
考慮S=∑qi (0≤i≤n),注意是有0.
就是1+q^1+q^2+....q^n
而後當n是偶數的時候:
把這個式子分紅先後相等長度的兩部分
(p^0+p^1+..p^(n/2))+ (p^(n/2+1)+p(n/2+2)+...+p^n)
把後半部分的p^(n/2+1)提取出來。
(p^0+p^1+..p^(n/2)) * (p^(n/2+1)+1)
右邊快速冪,左邊遞歸
奇數的話去掉p^n,一樣的操做去左邊遞歸右邊快速冪。
代碼:
#include<bits/stdc++.h> using namespace std; #define LL long long #define INF 2000000000 #define eps 1e-8 #define pi 3.141592653589793 long long q(LL a,LL n,LL mod) { LL ans = 1LL,temp = a%mod; while(n){ if(n&1){ ans=(ans*temp)%mod; } n>>=1; temp=(temp*temp)%mod; } return ans; } LL sum(LL p,LL n,LL mod) { if(p==0)return 0; if(n==0)return 1; return (n&1)?(((1+q(p,n/2+1,mod))%mod*sum(p,n/2,mod)%mod)%mod):(((1+q(p,n/2+1,mod))%mod*sum(p,n/2-1,mod)+q(p,n/2,mod)%mod)%mod); } int main() { /* LL a,b,p; while(~scanf("%lld %lld %lld",&a,&b,&p)){ LL sum = 0;for(int i = 1 ; i <= a ; i ++){ sum += q(b,i,p); sum%=p; } cout<<sum<<endl; } */ LL a,b,p; int _; for(scanf("%d",&_);_--;){ scanf("%lld %lld %lld",&a,&b,&p); LL ans = sum(b,a,p); printf("%lld\n",(ans+p-1)%p); } }/* 2 3 2 100 4 511 520 */
E:
描述
YuYu最近正在學習多位數的乘法,crq想考考她的學習狀況,但又懶得出題,所以直接拿了一副撲克牌。撲克牌去掉了大小王和牌面值較大的牌,只留下A、二、三、四、五、六、七、8 、9,每種花色有9張牌,牌面值分別爲1~9,現從中抽出n張牌,crq要求YuYu從n張牌中挑出若干張組成乘法公式a*b=c,其中a、b和c都可以由多張牌拼接而成(如1和2能拼成12,也能拼成21),但a和b最可能是2位的正整數(由於YuYu懼怕太大的數)。
如給定4 5 6 9四張牌,能夠組成:
6*9=54
9*6=54
一個公式中同一張牌最多隻能使用一次。
輸入
多組數據,第一行爲數據組數T(T<=100)。
每組數據第一行爲正整數n(n<=36),第二行爲n個正整數,表示從一副牌中抽取的牌面值,全部牌面值在1到9之間。
輸出
對於每組數據,輸出最多有多少種可能的公式。
樣例輸入
2
4
6 9 5 4
5
1 6 6 6 9
樣例輸出
2
4
思路:
注意C沒限制是兩位數便可
一眼感受是36^4*100的題,實際100*100兩個循環判斷就好了。
交了打表代碼過了。。不是很懂。
實際我操做的是 一個兩位數乘以一個兩位數等於一個四位數,好比說什麼01*02=0004前面補個0
代碼:
#include<bits/stdc++.h> using namespace std; #define LL long long #define INF 2000000000 #define eps 1e-8 #define pi 3.141592653589793 string change(int a1,int a2,int a3,int a4,int a5,int a6,int a7,int a8){ string s = ""; s += (a2+'0'); s += (a1+'0'); s += '*'; s += (a4+'0'); s += (a3+'0'); s += '='; s += (a8+'0'); s += (a7+'0'); s += (a6+'0'); s += (a5+'0'); return s; } set<string>s; int main(){ int _; while(~scanf("%d",&_)){ while(_--){ s.clear(); int n,a[40], cnt[12]; memset(cnt,0,sizeof(cnt)); scanf("%d",&n); for(int i = 0 ; i < n ; i ++){ scanf("%d",a+i); cnt[a[i]]++; } int sum = 0; for(int i = 1 ; i < 100 ; i++){ for(int j = 1 ; j < 100 ; j++){ int temp = i; int num1 = temp%10; int num2 = temp/10%10; temp = j; int num3 = temp%10;//個位 int num4 = temp/10%10;//十位 temp = i*j; int num5 = temp%10;//個位 temp/=10; int num6 = temp%10;//十位 temp/=10; int num7 = temp%10;//百位 temp/=10; int num8 = temp%10;//千位 if(num1 == 0||num3 == 0||num5 == 0)continue; if(num8 != 0){ if(num7 == 0 || num6==0)continue; }else{ if(num7!=0){ if(num6==0)continue; } else{ if(num6!=0){ if(num5 == 0)continue; } } } //cout<<num8<<num7<<num6<<num5<<endl; if(num1 != 0) cnt[num1]--; if(num2 != 0) cnt[num2]--; if(num3 != 0) cnt[num3]--; if(num4 != 0) cnt[num4]--; if(num5 != 0) cnt[num5]--; if(num6 != 0) cnt[num6]--; if(num7 != 0) cnt[num7]--; if(num8 != 0) cnt[num8]--; if( cnt[num1] >= 0 && cnt[num2] >= 0 && cnt[num3] >= 0 && cnt[num4] >= 0 && cnt[num5] >= 0 && cnt[num6] >= 0 && cnt[num7] >= 0 && cnt[num8] >= 0 ){ string ss = change(num1,num2,num3,num4,num5,num6,num7,num8); s.insert(ss); } if(num1 != 0) cnt[num1]++; if(num2 != 0) cnt[num2]++; if(num3 != 0) cnt[num3]++; if(num4 != 0) cnt[num4]++; if(num5 != 0) cnt[num5]++; if(num6 != 0) cnt[num6]++; if(num7 != 0) cnt[num7]++; if(num8 != 0) cnt[num8]++; } } // for(set<string>::iterator it = s.begin() ; it != s.end();it++){ // cout<<*it<<endl; // } printf("%d\n",s.size()); }} } /* */
H:
描述
桃子很喜歡數學,最近他對lcm(最小公倍數)很是感興趣。小翁看到桃子在紙上寫了一大堆數學公式,就想考考桃子。他給小桃出了個題:如今你手上有一個數b,對於每一個1≤a≤1018,他把lcm(a,b)/a的不一樣值寫在了紙上,他想問你,他能在紙上寫幾個不一樣的數字。
輸入
第一行一個整數T(≤50),表明有T組數據。
對於每組數據,第一行一個整數b(1≤n≤1010),表明小桃手上的數b。
輸出
輸出一個數表明不一樣值的個數。
樣例輸入
2
1
2
樣例輸出
1
2
提示
第一個樣例,b等於1,只有1個值1。
第二個樣例,b等於2,只有2個值1和2。
思路:
打個表(a 從1到b+10 )
就能發現當a > b時候題目那個式子答案都同樣。而後出現的不同的值都是b的約數。因此題目轉化成了求b的約數個數。
(首A拿到了,笑)
複雜度是O(sqrt(n))
代碼:
#include<bits/stdc++.h> using namespace std; #define LL long long #define INF 2000000000 #define eps 1e-8 #define pi 3.141592653589793 int main() { int n; scanf("%d",&n); while(n--){ LL a;int sum = 0; scanf("%lld",&a); LL k = sqrt(a); for(int i = 1 ; i <= k; i++){ if(a%i==0){ sum+=2; } } if(k*k==a)sum--; printf("%d\n",sum); } return 0; }/* */
I:
描述
C++課上,老師講到了映射map,桃子以爲映射很神奇,能夠把一個串變成一個數存儲,也能夠把一堆很大的數字變成很小的數字。爲了加深對映射的印象,桃子出了下面這個題:
桃子將給你一個長的十進制數a,包含n個1-9的數字,你有一個映射函數f能夠把x變成f(x)。
你能夠執行如下操做不超過1次:選擇一個非空的連續子段並把裏面的每一個數字x映射成f(x)。例如a=1337,f(1)=1,f(3)=5,f(7)=3,你將選擇區間[2,3],並把3變成f(3)=5,最終獲得1557。
如今你執行了操做不超過1次,你能夠獲得的最大數是多少。
輸入
第一行一個整數T(1≤T≤95),表明有T組數據。
對於每組數據:
第一行爲一個整數n(1≤n≤2*105),爲十進制數a的長度。
第二行爲n個數字組成的整數a:a1a2...an(1≤ai≤9)。
第三行爲9個數字f(1),f(2),...,f(9),表明映射函數f。
數據保證∑n<=106。
輸出
每組數據輸出一行,表明桃子能獲得的最大值。
樣例輸入
3
4
1337
1 2 5 4 6 6 3 1 9
5
11111
9 8 7 6 5 4 3 2 1
2
33
1 1 1 1 1 1 1 1 1
樣例輸出
1557
99999
33
思路:
記第i個數是num[i];
從前日後遍歷第一個f(num[i]) > num[i]的改掉是最優的。而後一個坑的點是,繼續遍歷下去的時候能夠是f(num[pos]) == num[pos]
舉個例子
5
32314
1 4 3 7 1 1 1 1 1
這個數的第四個1要修改爲爲1,可讓第五位的4變成7。
代碼:
#include<bits/stdc++.h> using namespace std; #define LL long long #define INF 2000000000 #define eps 1e-8 #define pi 3.141592653589793 char s[200011]; int main() { int _; for(scanf("%d",&_);_--;){ int n; scanf("%d %s",&n,s); int f[11]; for(int i = 1; i <= 9 ;i++){ scanf("%d",f+i); } for(int i = 0 ; i < n ; i++){ int a = s[i] - '0'; if(f[a] > a){ int pos = i; while(f[a] >= a && pos < n){ s[pos] = f[a]+'0'; pos++; a = s[pos] - '0'; } break; } } printf("%s\n",s); } }/* 3 4 1337 1 2 5 4 6 6 3 1 9 5 11111 9 8 7 6 5 4 3 2 1 5 32314 1 4 3 7 1 1 1 1 1 */
J:
描述
桃子喜歡收藏,尤爲是對項鍊有着奇怪的要求:每顆珠子的顏色必須不一樣。因爲各類緣由,他找不到這種項鍊,因此他決定本身給項鍊塗色。
如今他手上有n種不一樣顏色的塗料,項鍊(環形)上有n顆珠子,他想知道他有多少種不一樣的塗法。若一條項鍊能經過繞中心旋轉或翻轉而變成另外一個項鍊,則認爲是同一種塗法。
輸入
輸入第一行爲測試樣例組數T(1<=T<=10000)。
對於每組數據包含一個正整數n(1<=n<=106),表明不一樣顏色的塗料種數或珠子數目。
輸出
對於每組數據,輸出一個整數表明有多少種不一樣的塗法。結果對109+7取模。
樣例輸入
2
3
4
樣例輸出
1
3
思路:
打表以後發現是(n!)/2。猜了2發(n+1)*n/2。。。。老老實實打表吧。
n= 1,2時候須要另外判斷。(我是存數組而後直接輸出)
代碼:
#include<bits/stdc++.h> using namespace std; #define LL long long #define INF 2000000000 #define eps 1e-8 #define pi 3.141592653589793 const LL mod = 1e9+7; LL a[1000011]; int main() { a[0] = a[1] = a[2] = 1; for(int i = 3 ; i <= 1000000 ; i++){ a[i] = (a[i-1] * i)%mod; } int _; for(scanf("%d",&_);_--;){ int n; scanf("%d",&n); cout<<a[n-1]<<endl; } } /* 4 3 4 5 6 */
L:
描述
最近桃子愛上了博彩,一天他買了一張彩票,上面印着帶有n個數字的序列a1a2a3...an。
若是一張彩票是幸運的,當且僅當其知足以下所有條件:
1. 序列能被剛好分紅不相交的至少2段;
2. 每一段區間[l,r]的和都是相同的。
請你幫助桃子判斷他手上的彩票是否是幸運的。
例如123426是幸運的,它能夠分爲3段,12三、42和6,1+2+3=4+2=6。
不相交就是序列的每一個數字剛好屬於一個段。
輸入
第一行一個整數T(≤100),表明有T組數據。
對於每組數據,第一行一個整數n(2≤n≤100),表明彩票中數字序列的位數。
第二行爲一個長度爲n的數字序列a1a2a3...an(0≤ai≤9)。
輸出
若是這張彩票是幸運的,輸出YES,不然輸出NO。
樣例輸入
2
5
73452
4
1248
樣例輸出
YES
NO
提示
第一個樣例:能分紅3段,七、34和52,7=3+4=5+2。
第二個樣例:不能分出。
思路:
求個前綴和,暴力枚舉每一個區間可能的和,由於a_i都是很小的!!以後看看看看能不能劃分就好了。
坑點:若是全部的數都是0,也是能夠的。被這個坑了。
代碼:
#include<bits/stdc++.h> using namespace std; #define LL long long #define INF 2000000000 #define eps 1e-8 #define pi 3.141592653589793 int main() { int _; for(scanf("%d",&_);_--;){ int n; scanf("%d",&n); string s;cin>>s; int a[101],flag = 0; int sum[111]; memset(sum,0,sizeof(sum)); for(int i = 0 ; i < n ; i++){ a[i] = s[i] - '0'; if(i == 0)sum[i+1] = a[i]; else sum[i+1] = sum[i]+a[i]; } if(sum[n] == 0){ puts("YES");continue; } for(int i = 0; i < sum[n]; i ++){ int pos = 0; for(int j = 1 ; j <= n ; j++){ int nowsum = sum[j] - sum[pos]; if(nowsum == i){ pos = j; // printf("%d %d\n",i,pos); } } if(pos == n || sum[pos] == sum[n]){ flag = 1; break; } } flag ? puts("YES"):puts("NO"); } }/* 4 20 00101000021000200100 5 73452 4 1248 8 10101000 1~10 */