今天是BestCoder一周年纪念日. 比赛管理员Soda想要给每个参赛者准备一个纪念品. 商店里纪念品的单价是 p 元, 同时也可以花 q 元购买纪念品套装, 一个套装里有 m 个纪念品. 今天总共有 n 个参赛者, Soda想要知道最少需要花多少钱才可以给每个人都准备一个纪念品.
输入有多组数据. 第一行有一个整数 T (1≤T≤105) , 表示测试数据组数. 然后对于每组数据: 一行包含4个整数 n,m,p,q (1≤n,m,p,q≤104) .
对于每组数据输出最小花费.
2 1 2 2 1 1 2 3 4
1 3
对于第一组数据, Soda可以1元购买一个套装. 对于第二组数据, Soda可以直接花3元购买一个纪念品.
代码:
// C #ifndef _GLIBCXX_NO_ASSERT #include <cassert> #endif #include <cctype> #include <cerrno> #include <cfloat> #include <ciso646> #include <climits> #include <clocale> #include <cmath> #include <csetjmp> #include <csignal> #include <cstdarg> #include <cstddef> #include <cstdio> #include <cstdlib> #include <cstring> #include <ctime> // C++ #include <algorithm> #include <bitset> #include <complex> #include <deque> #include <exception> #include <fstream> #include <functional> #include <iomanip> #include <ios> #include <iosfwd> #include <iostream> #include <istream> #include <iterator> #include <limits> #include <list> #include <locale> #include <map> #include <memory> #include <new> #include <numeric> #include <ostream> #include <queue> #include <set> #include <sstream> #include <stack> #include <stdexcept> #include <streambuf> #include <string> #include <typeinfo> #include <utility> #include <valarray> #include <vector> using namespace std; #define rep(i,j,k) for(int i=(int)j;i<(int)k;++i) #define per(i,j,k) for(int i=(int)j;i>(int)k;--i) #define lowbit(a) a&-a #define Max(a,b) a>b?a:b #define Min(a,b) a>b?b:a #define mem(a,b) memset(a,b,sizeof(a)) typedef long long LL; typedef unsigned long long LLU; typedef double db; const int N=1e5+10; const int inf=0x3f3f3f3f; int t,ans,res,cnt,tmp; inline LL read() { int c=0,f=1; char ch=getchar(); while(ch<'0'||ch>'9') { if(ch=='-')f=-1; ch=getchar(); } while(ch>='0'&&ch<='9') { c=c*10+ch-'0'; ch=getchar(); } return c*f; } int n,m,p,q; int main() { t=read(); while(t--) { n=read(); m=read(); p=read(); q=read(); int h1=p*n;///全部买单价 int h2,h3; if(n%m==0){///倍数关系 h2 = n/m*q;///全部套装 } else{ h2 = (n/m+1)*q;///人数不够的,加一 } h3 = n/m*q + n%m*p;///n%m的零头买单价 printf("%d\n",min(h1,min(h2,h3))); } return 0; }
B Hidden String
今天是BestCoder一周年纪念日. 比赛管理员Soda有一个长度为 n 的字符串 s . 他想要知道能否找到 s 的三个互不相交的子串 s[l1..r1] , s[l2..r2] , s[l3..r3] 满足下列条件: 1. 1≤l1≤r1<l2≤r2<l3≤r3≤n 2. s[l1..r1] , s[l2..r2] , s[l3..r3] 依次连接之后得到字符串"anniversary".
输入有多组数据. 第一行有一个整数 T (1≤T≤100) , 表示测试数据组数. 然后对于每组数据: 一行包含一个仅含小写字母的字符串 s (1≤|s|≤100) .
对于每组数据, 如果Soda可以找到这样三个子串, 输出"YES", 否则输出"NO".
2 annivddfdersewwefary nniversarya
YES NO
// C #ifndef _GLIBCXX_NO_ASSERT #include <cassert> #endif #include <cctype> #include <cerrno> #include <cfloat> #include <ciso646> #include <climits> #include <clocale> #include <cmath> #include <csetjmp> #include <csignal> #include <cstdarg> #include <cstddef> #include <cstdio> #include <cstdlib> #include <cstring> #include <ctime> // C++ #include <algorithm> #include <bitset> #include <complex> #include <deque> #include <exception> #include <fstream> #include <functional> #include <iomanip> #include <ios> #include <iosfwd> #include <iostream> #include <istream> #include <iterator> #include <limits> #include <list> #include <locale> #include <map> #include <memory> #include <new> #include <numeric> #include <ostream> #include <queue> #include <set> #include <sstream> #include <stack> #include <stdexcept> #include <streambuf> #include <string> #include <typeinfo> #include <utility> #include <valarray> #include <vector> using namespace std; #define rep(i,j,k) for(int i=(int)j;i<(int)k;++i) #define per(i,j,k) for(int i=(int)j;i>(int)k;--i) #define lowbit(a) a&-a #define Max(a,b) a>b?a:b #define Min(a,b) a>b?b:a #define mem(a,b) memset(a,b,sizeof(a)) typedef long long LL; typedef unsigned long long LLU; typedef double db; const int N=1e5+10; const int inf=0x3f3f3f3f; char str[N]; bool vis[N]; int dir4[4][2]= {{1,0},{0,1},{-1,0},{0,-1}}; int dir8[8][2]= {{1,0},{1,1},{0,1},{-1,1},{-1,0},{-1,-1},{0,-1},{1,-1}}; int movv[5][2]= {{1,0},{0,1},{0,0},{-1,0},{0,-1}}; inline LL read() { int c=0,f=1; char ch=getchar(); while(ch<'0'||ch>'9') { if(ch=='-')f=-1; ch=getchar(); } while(ch>='0'&&ch<='9') { c=c*10+ch-'0'; ch=getchar(); } return c*f; } int t,n,m,p,q,len; int ok; char s1[N]; char pp[12]="anniversary"; void dfs(int u,int k,int num) { if(k==11&&num==3){ ok=1; return ; } for(int i=u; i<len; ++i){ int h1=k; while(s1[i]==pp[h1]) { dfs(i+1,h1+1,num+1); i++; h1++; } } } int main() { t=read(); while(t--){ scanf("%s",&s1); len=strlen(s1); ok=0; dfs(0,0,0); if(ok) puts("YES"); else puts("NO"); } return 0; }C Sequence
Soda习得了一个数列, 数列的第 n (n≥1) 项是 3n(n−1)+1 . 现在他想知道对于一个给定的整数 m , 是否可以表示成若干项上述数列的和. 如果可以, 那么需要的最小项数是多少? 例如, 22可以表示为 7+7+7+1 , 也可以表示为 19+1+1+1 .
输入有多组数据. 第一行有一个整数 T (1≤T≤104) , 表示测试数据组数. 然后对于每组数据: 一行包含1个整数 m (1≤m≤109) .
对于每组数据输出最小花费.
10 1 2 3 4 5 6 7 8 22 10
1 2 3 4 5 6 1 2 4 4【解题思路】:AC率 1.7%,暂时没有想到好的解法~~
D Bipartite Graph
Soda有一个 n 个点 m 条边的二分图, 他想要通过加边使得这张图变成一个边数最多的完全二分图. 于是他想要知道他最多能够新加多少条边. 注意重边是不允许的.
输入有多组数据. 第一行有一个整数 T (1≤T≤100) , 表示测试数据组数. 然后对于每组数据: 第一行报包含两个整数 n 和 m , (2≤n≤10000,0≤m≤100000) . 接下来 m 行, 每行两个整数 u 和 v (1≤u,v≤n,v≠u) , 表示 u 和 v 之间有一条无向边. 输入保证给出的图是二分图, 没有重边, 没有自环. 大部分数据都是小数据.
对于每组数据, 输出Soda最多能加的边数.
2 4 2 1 2 2 3 4 4 1 2 1 4 2 3 3 4
2 0
首先二分图可以分成两类点 X 和 Y , 完全二分图的边数就是 |X|⋅|Y| .我们的目的是 max{|X|⋅|Y|} , 并且 |X|+|Y|=n . 把原图黑白染色, 每个联通块有 ai 个黑点, bi 个白点, 于是就是要确定 ai 属于 X 还是属于 Y . 然后我们考虑dp, dpi,x 表示用了前 i 个联通块, |X|=x 是否可行. dp方程很容易确定, dpi,x=dpi−1,x−a[i] or dpi−1,x−b[i] . 直接暴力是 O(n2) 的, 可以考虑用bitset优化, 这样就可以过了. 实际上由于数据很难造, 一些稍加优化的 n2 也可以过的
#ifndef _GLIBCXX_NO_ASSERT #include <cassert> #endif #include <cctype> #include <cerrno> #include <cfloat> #include <ciso646> #include <climits> #include <clocale> #include <cmath> #include <csetjmp> #include <csignal> #include <cstdarg> #include <cstddef> #include <cstdio> #include <cstdlib> #include <cstring> #include <ctime> // C++ #include <algorithm> #include <bitset> #include <complex> #include <deque> #include <exception> #include <fstream> #include <functional> #include <iomanip> #include <ios> #include <iosfwd> #include <iostream> #include <istream> #include <iterator> #include <limits> #include <list> #include <locale> #include <map> #include <memory> #include <new> #include <numeric> #include <ostream> #include <queue> #include <set> #include <sstream> #include <stack> #include <stdexcept> #include <streambuf> #include <string> #include <typeinfo> #include <utility> #include <valarray> #include <vector> using namespace std; #define rep(i,j,k) for(int i=(int)j;i<(int)k;++i) #define per(i,j,k) for(int i=(int)j;i>(int)k;--i) #define lowbit(a) a&-a #define Max(a,b) a>b?a:b #define Min(a,b) a>b?b:a #define mem(a,b) memset(a,b,sizeof(a)) typedef long long LL; typedef unsigned long long LLU; typedef double db; const int N=1e5+10; const int inf=0x3f3f3f3f; char str[N]; bool vis[N]; int dir4[4][2]= {{1,0},{0,1},{-1,0},{0,-1}}; int dir8[8][2]= {{1,0},{1,1},{0,1},{-1,1},{-1,0},{-1,-1},{0,-1},{1,-1}}; int movv[5][2]= {{1,0},{0,1},{0,0},{-1,0},{0,-1}}; inline LL read() { int c=0,f=1; char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){c=c*10+ch-'0';ch=getchar();} return c*f; } __int64 t,n,m,p,q,u,v; int len; char s1[N]; char s2[N]; int ok; struct graph { int mat[2]; } g[N]; vector<int>V[N]; int vec; void dfs(int u,int k) { vis[u]=true; g[vec].mat[k]++; for(int i=0; i<V[u].size(); i++){ int v=V[u][i]; if (!vis[v]) dfs(v,k^1); } } bool cmp(const graph &x,const graph &y) { return x.mat[0]-x.mat[1] > y.mat[0]-y.mat[1]; } int main() { t=read(); while(t--){ scanf("%I64d%I64d",&n,&m); for(int i=1; i<=n; i++){ V[i].clear(); vis[i]=0; } for(int i=1; i<=m; i++){ u=read(); v=read(); V[u].push_back(v); V[v].push_back(u); } vec=0; for(int i=1; i<=n; i++){ if (!vis[i]){ g[vec].mat[0]=g[vec].mat[1]=0; dfs(i,0); vec++; } } for(int i=0; i<vec; i++){ if (g[i].mat[0]<g[i].mat[1]) swap(g[i].mat[0],g[i].mat[1]); } sort(g,g+vec,cmp); __int64 x=0,y=0; for (int i=0; i<vec; i++){ if(x>y) swap(x,y); x+=g[i].mat[0]; y+=g[i].mat[1]; } printf("%I64d\n",x*y-m); } return 0; }