做atcoder总是感到格外的智商不足……感觉atcoder比起codeforces来说题目普遍更有趣,更考验思维orz
C
题意:给出无向图,距离为3的点如果未连边,则可以连上一条边,问最多能连多少边。
解题思路:
易证距离(可以非简单路)为奇数的均可以连边。
如果是二分图,则图中不存在奇环,最终状态二分图两部的点彼此有连边。
非二分图的连通图一定存在奇环,则任意两点若初始距离非奇数,加上奇环之后距离就必可变为奇数。最终状态为完全图。
按最终状态的边数减去当下边数即可。
1 #include <cstdio> 2 #include <iostream> 3 #include <algorithm> 4 #include <vector> 5 #include <set> 6 #include <map> 7 #include <string> 8 #include <cstring> 9 #include <stack> 10 #include <queue> 11 #include <cmath> 12 #include <ctime> 13 #include <bitset> 14 #include <utility> 15 #include <assert.h> 16 using namespace std; 17 #define rank rankk 18 #define mp make_pair 19 #define pb push_back 20 #define xo(a,b) ((b)&1?(a):0) 21 #define tm tmp 22 //#pragma comment(linker, "/STACK:1024000000,1024000000") 23 //#define LL ll 24 typedef unsigned long long ull; 25 typedef pair<int,int> pii; 26 typedef long long ll; 27 typedef pair<ll,int> pli; 28 typedef pair<ll,ll> pll; 29 const int INF=0x3f3f3f3f; 30 const ll INFF=0x3f3f3f3f3f3f3f3fll; 31 const int MAX=1e5+10; 32 //const ll MAXN=2e8; 33 //const int MAX_N=MAX; 34 const ll MOD=998244353; 35 //const long double pi=acos(-1.0); 36 //const double eps=0.00000001; 37 ll gcd(ll a,ll b){return b?gcd(b,a%b):a;} 38 template<typename T>inline T abs(T a) {return a>0?a:-a;} 39 template<class T> inline 40 void read(T& num) { 41 bool start=false,neg=false; 42 char c; 43 num=0; 44 while((c=getchar())!=EOF) { 45 if(c=='-') start=neg=true; 46 else if(c>='0' && c<='9') { 47 start=true; 48 num=num*10+c-'0'; 49 } else if(start) break; 50 } 51 if(neg) num=-num; 52 } 53 inline ll powMM(ll a,ll b,ll M){ 54 ll ret=1; 55 a%=M; 56 // b%=M; 57 while (b){ 58 if (b&1) ret=ret*a%M; 59 b>>=1; 60 a=a*a%M; 61 } 62 return ret; 63 } 64 void open() 65 { 66 // freopen("1009.in","r",stdin); 67 freopen("out.txt","w",stdout); 68 } 69 int n,m,u,v; 70 const int maxn=1e5+5; 71 vector<int> G[maxn]; 72 int color[maxn]; 73 bool bipartite(int u) 74 { 75 for(int i=0;i<G[u].size();i++) 76 { 77 int v=G[u][i]; 78 if(color[v]==color[u])return false; 79 if(!color[v]) 80 { 81 color[v]=3-color[u]; 82 if(!bipartite(v))return false; 83 } 84 } 85 return true; 86 } 87 int cnt1; 88 int main() 89 { 90 scanf("%d%d",&n,&m); 91 for(int i=1;i<=m;i++) 92 { 93 scanf("%d%d",&u,&v);G[u].pb(v);G[v].pb(u); 94 } 95 color[1]=1; 96 if(bipartite(1)) 97 { 98 for(int i=1;i<=n;i++) 99 if(color[i]==1)++cnt1; 100 printf("%lld ",1LL*(n-cnt1)*cnt1-m); 101 } 102 else printf("%lld ",1LL*n*(n-1)/2LL-m); 103 return 0; 104 }
D
题意:给出01字符串,每次操作将101变为010,问最多做多少次操作。
解题思路:
注意到只有 若干个1+0+若干个1 的形式才能进行操作。
且实际上每次只有 x个1+0+1 1+0+x个1这部分会操作 像11011 实际上操作只能选择最初的4个数,或末尾的4个数 因为101操作后1的周围就被0包围,进行2次之后就与另一部分的1隔开了2个0,无法与之继续操作。
故考虑dp,只需要对每个 x个1+0+1 和1+0+x个1的dp即可。
x个1+0+1的操作次数为x。
1 #include <cstdio> 2 #include <iostream> 3 #include <algorithm> 4 #include <vector> 5 #include <set> 6 #include <map> 7 #include <string> 8 #include <cstring> 9 #include <stack> 10 #include <queue> 11 #include <cmath> 12 #include <ctime> 13 #include <bitset> 14 #include <utility> 15 #include <assert.h> 16 using namespace std; 17 #define rank rankk 18 #define mp make_pair 19 #define pb push_back 20 #define xo(a,b) ((b)&1?(a):0) 21 #define tm tmp 22 //#pragma comment(linker, "/STACK:1024000000,1024000000") 23 //#define LL ll 24 typedef unsigned long long ull; 25 typedef pair<int,int> pii; 26 typedef long long ll; 27 typedef pair<ll,int> pli; 28 typedef pair<ll,ll> pll; 29 const int INF=0x3f3f3f3f; 30 const ll INFF=0x3f3f3f3f3f3f3f3fll; 31 const int MAX=5e5+10; 32 //const ll MAXN=2e8; 33 //const int MAX_N=MAX; 34 const ll MOD=10007; 35 //const long double pi=acos(-1.0); 36 //const double eps=0.00000001; 37 ll gcd(ll a,ll b){return b?gcd(b,a%b):a;} 38 template<typename T>inline T abs(T a) {return a>0?a:-a;} 39 template<class T> inline 40 void read(T& num) { 41 bool start=false,neg=false; 42 char c; 43 num=0; 44 while((c=getchar())!=EOF) { 45 if(c=='-') start=neg=true; 46 else if(c>='0' && c<='9') { 47 start=true; 48 num=num*10+c-'0'; 49 } else if(start) break; 50 } 51 if(neg) num=-num; 52 } 53 inline ll powMM(ll a,ll b,ll M){ 54 ll ret=1; 55 a%=M; 56 // b%=M; 57 while (b){ 58 if (b&1) ret=ret*a%M; 59 b>>=1; 60 a=a*a%M; 61 } 62 return ret; 63 } 64 void open() 65 { 66 // freopen("1009.in","r",stdin); 67 freopen("out.txt","w",stdout); 68 } 69 70 int n; 71 char a[MAX]; 72 int num[MAX],dp[MAX]; 73 int an,tem; 74 int main() 75 { 76 scanf("%d",&n); 77 scanf("%s",a+1); 78 for(int i=1;i<=n;i++) 79 { 80 if(a[i]=='1') 81 num[i]=num[i-1]+1; 82 } 83 for(int i=n-1;i>=1;i--) 84 if(a[i]=='1') 85 num[i]=max(num[i],num[i+1]); 86 for(int i=2;i<=n-1;i++) 87 { 88 if(a[i]=='0'&&a[i-1]=='1'&&a[i+1]=='1') 89 { 90 for(int j=1;j<=num[i+1];j++) 91 dp[i+j]=max(dp[i-2]+j,dp[i+j]); 92 for(int j=1;j<=num[i-1];j++) 93 dp[i+1]=max(dp[i+1],dp[i-j-1]+j); 94 } 95 dp[i]=max(dp[i],dp[i-1]); 96 an=max(an,dp[i]); 97 } 98 an=max(an,dp[n]); 99 an=max(an,dp[n+1]); 100 101 printf("%d ",an); 102 }
E
题意:A个红球,B个蓝球,按前A个是红,后B个是蓝摆成一行。任选s 两个位置,每次取出该行行首或s位置或t位置的球。所有的蓝、红球认为是一样的,问有多少种不同的取法。(两种取法认为是不同的,当且仅当存在某次取出,取出的球颜色不同)
以下代码是完全依照官方题解写的。
从(A,B)走到与第一个三角形的交点的距离是固定的(因为三角形边界的斜率为-1)方案数只与纵坐标之差有关。
同理到与第二个三角形的交点的方案数也只与纵坐标之差有关。下面考虑两个三角形位置和大小的选择。均为等腰直角三角形,设其直角边长度分别为x,y,则x>=s,y>=t,x+y<=A,取法个数为C(a-s-t+2,2)
(对于a个位置取出s+t个,加上边界的2个,选出2个位置,之后再加上s 保证满足前面的限制条件,总方法即为此)
枚举s 即可。
1 #include <cstdio> 2 #include <iostream> 3 #include <algorithm> 4 #include <vector> 5 #include <set> 6 #include <map> 7 #include <string> 8 #include <cstring> 9 #include <stack> 10 #include <queue> 11 #include <cmath> 12 #include <ctime> 13 #include <bitset> 14 #include <utility> 15 #include <assert.h> 16 using namespace std; 17 #define rank rankk 18 #define mp make_pair 19 #define pb push_back 20 #define xo(a,b) ((b)&1?(a):0) 21 #define tm tmp 22 //#pragma comment(linker, "/STACK:1024000000,1024000000") 23 //#define LL ll 24 typedef unsigned long long ull; 25 typedef pair<int,int> pii; 26 typedef long long ll; 27 typedef pair<ll,int> pli; 28 typedef pair<ll,ll> pll; 29 const int INF=0x3f3f3f3f; 30 const ll INFF=0x3f3f3f3f3f3f3f3fll; 31 const int MAX=5e5+10; 32 //const ll MAXN=2e8; 33 //const int MAX_N=MAX; 34 const ll MOD=1e9+7; 35 //const long double pi=acos(-1.0); 36 //const double eps=0.00000001; 37 ll gcd(ll a,ll b){return b?gcd(b,a%b):a;} 38 template<typename T>inline T abs(T a) {return a>0?a:-a;} 39 template<class T> inline 40 void read(T& num) { 41 bool start=false,neg=false; 42 char c; 43 num=0; 44 while((c=getchar())!=EOF) { 45 if(c=='-') start=neg=true; 46 else if(c>='0' && c<='9') { 47 start=true; 48 num=num*10+c-'0'; 49 } else if(start) break; 50 } 51 if(neg) num=-num; 52 } 53 inline ll powMM(ll a,ll b,ll M){ 54 ll ret=1; 55 a%=M; 56 // b%=M; 57 while (b){ 58 if (b&1) ret=ret*a%M; 59 b>>=1; 60 a=a*a%M; 61 } 62 return ret; 63 } 64 void open() 65 { 66 // freopen("1009.in","r",stdin); 67 freopen("out.txt","w",stdout); 68 } 69 70 const int N = 2020; 71 ll C[N][N]; 72 void init() { 73 for (int i = 0; i < N; i ++) C[i][0] = C[i][i] = 1; 74 for (int i = 1; i < N; i ++) { 75 for (int j = 1; j < i; j ++) { 76 C[i][j] = (C[i - 1][j] + C[i - 1][j - 1]) % MOD; 77 } 78 } 79 } 80 int a,b; 81 ll an,lin; 82 int main() 83 { 84 init(); 85 scanf("%d%d",&a,&b); 86 an=a+1; 87 for(int i=1;i<=min(a,b-1);i++)//第一次向下的位置的横坐标 88 { 89 for(int j=0;j<i&&j+i<=a;j++) 90 { 91 lin=C[b-1][i]*C[i-1][j]%MOD*C[a-i-j+2][2]%MOD; 92 an=(an+lin)%MOD; 93 } 94 } 95 printf("%lld ",an); 96 97 }
F
如果一个环由2部分构成(长度不一定相同,但同一部分的位置不能改变,且每一部分的任意前缀串s,其任意长度的后缀均比相同长度的前缀字典序”不小于”)设两部分分别为xy
将其连接而成的一个环,只可能由这两部分的起始位置作为起点的串可能为Smallest Cyclic Shift(以下简写为SCS)因为取某部分的后缀作为开头,则其已经不小于该部分的前缀,如果是大于显然取前缀作为开头更优,如果是等于,最后比较的还是两部分的前缀。
而x、y比较得x字典序更小,故xy即为所求的字符串。
一般地,如果一个环由k部分构成(k>=3),易证在欲使最终的SCS最大的情况下,将k部分转化成k-1部分,一定是选择字典序最小的部分与字典序最大的部分相连。
最初有x+y+z个部分,分别是x个a,y个b,z个c,将其按上述操作反复进行即可。
1 #include <cstdio> 2 #include <iostream> 3 #include <algorithm> 4 #include <vector> 5 #include <set> 6 #include <map> 7 #include <string> 8 #include <cstring> 9 #include <stack> 10 #include <queue> 11 #include <cmath> 12 #include <ctime> 13 #include <bitset> 14 #include <utility> 15 #include <assert.h> 16 using namespace std; 17 #define rank rankk 18 #define mp make_pair 19 #define pb push_back 20 #define xo(a,b) ((b)&1?(a):0) 21 #define tm tmp 22 //#pragma comment(linker, "/STACK:1024000000,1024000000") 23 //#define LL ll 24 typedef unsigned long long ull; 25 typedef pair<int,int> pii; 26 typedef long long ll; 27 typedef pair<ll,int> pli; 28 typedef pair<ll,ll> pll; 29 const int INF=0x3f3f3f3f; 30 const ll INFF=0x3f3f3f3f3f3f3f3fll; 31 const int MAX=5e5+10; 32 //const ll MAXN=2e8; 33 //const int MAX_N=MAX; 34 const ll MOD=1e9+7; 35 //const long double pi=acos(-1.0); 36 //const double eps=0.00000001; 37 ll gcd(ll a,ll b){return b?gcd(b,a%b):a;} 38 template<typename T>inline T abs(T a) {return a>0?a:-a;} 39 template<class T> inline 40 void read(T& num) { 41 bool start=false,neg=false; 42 char c; 43 num=0; 44 while((c=getchar())!=EOF) { 45 if(c=='-') start=neg=true; 46 else if(c>='0' && c<='9') { 47 start=true; 48 num=num*10+c-'0'; 49 } else if(start) break; 50 } 51 if(neg) num=-num; 52 } 53 inline ll powMM(ll a,ll b,ll M){ 54 ll ret=1; 55 a%=M; 56 // b%=M; 57 while (b){ 58 if (b&1) ret=ret*a%M; 59 b>>=1; 60 a=a*a%M; 61 } 62 return ret; 63 } 64 void open() 65 { 66 // freopen("1009.in","r",stdin); 67 freopen("out.txt","w",stdout); 68 } 69 int x,y,z; 70 vector<string>s; 71 int main() 72 { 73 scanf("%d%d%d",&x,&y,&z); 74 for(int i=0;i<x;i++)s.pb("a"); 75 for(int i=0;i<y;i++)s.pb("b"); 76 for(int j=0;j<z;j++)s.pb("c"); 77 while(s.size()>1) 78 { 79 sort(s.begin(),s.end()); 80 s[0]+=s[s.size()-1]; 81 s.pop_back(); 82 } 83 cout<<s[0]<<" "; 84 } 85 /* 86 8 87 11011011 88 */