problem 1001
Souvenir
Accepts: 901
Submissions: 2743
Time Limit: 2000/1000 MS (Java/Others)
Memory Limit: 262144/262144 K (Java/Others)
问题描述
今天是BestCoder一周年纪念日. 比赛管理员Soda想要给每个参赛者准备一个纪念品. 商店里纪念品的单价是p元, 同时也可以花q元购买纪念品套装, 一个套装里有mm个纪念品. 今天总共有nn个参赛者, Soda想要知道最少需要花多少钱才可以给每个人都准备一个纪念品.
输入描述
输入有多组数据. 第一行有一个整数TT (1 \le T \le 10^5)(1≤T≤10?5??), 表示测试数据组数. 然后对于每组数据: 一行包含4个整数 n, m, p, q (1 \le n, m, p, q \le 10^4)(1≤n,m,p,q≤10?4??).
输出描述
对于每组数据输出最小花费.
输入样例
2 1 2 2 1 1 2 3 4
输出样例
1 3
Hint
对于第一组数据, Soda可以1元购买一个套装. 对于第二组数据, Soda可以直接花3元购买一个纪念品. 思路:当m小于n,你可以就p*m与q谁大谁小进行选择,当m大于n,就p*n与q谁大谁小进行考虑
#include <iostream> #include <cstdio> using namespace std; int main() { int T; cin>>T; int n,m,p,q; while(T--) { cin>>n>>m>>p>>q; int sum=0; while(n>=m) { if(p*m>q) sum+=q; else sum+=p*m; n-=m; } if(p*n<q) sum+=p*n; else sum+=q; cout<<sum<<endl; } return 0; }
problem1002
Hidden String
Accepts: 437
Submissions: 2174
Time Limit: 2000/1000 MS (Java/Others)
Memory Limit: 262144/262144 K (Java/Others)
问题描述
今天是BestCoder一周年纪念日. 比赛管理员Soda有一个长度为nn的字符串ss. 他想要知道能否找到ss的三个互不相交的子串s[l_1..r_1]s[l?1??..r?1??], s[l_2..r_2]s[l?2??..r?2??], s[l_3..r_3]s[l?3??..r?3??]满足下列条件: 1. 1 \le l_1 \le r_1 < l_2 \le r_2 < l_3 \le r_3 \le n1≤l?1??≤r?1??<l?2??≤r?2??<l?3??≤r?3??≤n 2. s[l_1..r_1]s[l?1??..r?1??], s[l_2..r_2]s[l?2??..r?2??], s[l_3..r_3]s[l?3??..r?3??]依次连接之后得到字符串"anniversary".
输入描述
输入有多组数据. 第一行有一个整数TT (1 \le T \le 100)(1≤T≤100), 表示测试数据组数. 然后对于每组数据: 一行包含一个仅含小写字母的字符串ss (1 \le |s| \le 100)(1≤∣s∣≤100).
输出描述
对于每组数据, 如果Soda可以找到这样三个子串, 输出"YES", 否则输出"NO".
输入样例
2 annivddfdersewwefary nniversarya
输出样例
YES NO 可以使用搜索求,字符串长度也不算长。。。。。。。
#include <iostream> #include <cstring> #include <cstdio> using namespace std; char goal[]="anniversary"; char a[110]; int len,glen; void Init() { cin>>a; len=strlen(a); } bool DFS(int ti,int gi,int num) { if(ti<=len&&gi>=glen&&num<=3) return true; if(num>3) return false; for(int i=ti;i<len;i++) { int si=i,sg=gi; while(si<len&&sg<glen&&a[si]==goal[sg]) sg++,si++; if(si!=i&&DFS(si,sg,num+1)) return true; } return false; } void Work() { if(DFS(0,0,0)) cout<<"YES"<<endl; else cout<<"NO"<<endl; } int main() { int T; glen=strlen(goal); cin>>T; while(T--) { Init(); Work(); } return 0; }
problem1003
Sequence
Accepts: 25
Submissions: 1442
Time Limit: 2000/2000 MS (Java/Others)
Memory Limit: 262144/262144 K (Java/Others)
问题描述
Soda习得了一个数列, 数列的第nn (n \ge 1)(n≥1)项是3n(n-1)+13n(n−1)+1. 现在他想知道对于一个给定的整数mm, 是否可以表示成若干项上述数列的和. 如果可以, 那么需要的最小项数是多少? 例如, 22可以表示为7+7+7+17+7+7+1, 也可以表示为19+1+1+119+1+1+1.
输入描述
输入有多组数据. 第一行有一个整数TT (1 \le T \le 10^4)(1≤T≤10?4??), 表示测试数据组数. 然后对于每组数据: 一行包含1个整数 mm (1 \le m \le 10^9)(1≤m≤10?9??).
输出描述
对于每组数据输出最小花费.
输入样例
10 1 2 3 4 5 6 7 8 22 10
输出样例
1 2 3 4 5 6 1 2 4 4
官方题解:
这个题看上去是一个贪心, 但是这个贪心显然是错的. 事实上这道题目很简单, 先判断1个是否可以, 然后判断2个是否可以. 之后找到最小的k (k > 2)k(k>2), 使得(m - k) mod 6 = 0(m−k)mod6=0即可.
证明如下: 3n(n-1)+1 = 6(n*(n-1)/2)+13n(n−1)+1=6(n∗(n−1)/2)+1, 注意到n*(n-1)/2n∗(n−1)/2是三角形数, 任意一个自然数最多只需要3个三角形数即可表示. 枚举需要kk个, 那么显然m=6(km=6(k个三角形数的和)+k)+k, 由于k \ge 3k≥3, 只要m-km−k是6的倍数就一定是有解的
#include <iostream> #include <cstdio> using namespace std; const int maxn=1e5+10; int n; int a[maxn]; int caculate(int m) { for(int i=1;i<=n;i++) { if(a[i]==m) return 1; } int j=n; for(int i=1;i<=n&&a[i]<m;i++) { while(a[i]+a[j]>m) j--; if(a[i]+a[j]==m) return 2; } return 0; } int main() { int T; for(int i=1;i<maxn;i++) { a[i]=3*i*(i-1)+1; if(a[i]>1e9) { n=i; break; } } cin>>T; while(T--) { int m,ans; cin>>m; for(int k=1;k<=m;k++) { if(k==1||k==2) { ans=caculate(m); if(ans!=0) break; } else { if((m-k)%6==0) {ans=k;break;} } } cout<<ans<<endl; } return 0; }
时间: 2024-10-10 01:10:17