前言
最近打算打一段时间TC和CF。
题目及代码
300
题目很简单,把数字排一下序,然后数字之间挨个贪心插入”+”就行了。
代码:
#include <vector>
#include <list>
#include <map>
#include <set>
#include <deque>
#include <stack>
#include <bitset>
#include <algorithm>
#include <functional>
#include <numeric>
#include <utility>
#include <sstream>
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <cstring>
using namespace std;
typedef long long LL;
typedef vector <int> VI;
typedef pair <int,int> PII;
#define FOR(i,x,y) for(int i = x;i < y;++ i)
#define IFOR(i,x,y) for(int i = x;i > y;-- i)
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define lrt rt<<1
#define rrt rt<<1|1
#define lson rt<<1,l,mid
#define rson rt<<1|1,mid+1,r
int in(){
int ans=0;
char last=' ',ch=getchar();
while(ch<'0' || ch>'9')last=ch,ch=getchar();
while(ch>='0' && ch<='9')ans=ans*10+ch-'0',ch=getchar();
if(last=='-')ans=-ans;
return ans;
}
void out(int a) {
if(a < 0) { putchar('-'); a = -a; }
if(a >= 10) out(a / 10);
putchar(a % 10 + '0');
}
const int maxn = 100;
class Plusonegame
{
public:
string getorder(string s)
{
int cnt = 0;
string ans = string("");
char p = '+';
char str[maxn];
int len = 0;
int slen = s.length();
FOR(i,0,slen){
if(s[i] == '+') {cnt ++;continue;}
str[len++] = s[i];
}
sort(str,str+len);
int cur = 0;
for(int i = 0;i < len;i++){
int t = str[i]-'0';
while(cnt && cur < t){
ans += p;
cur ++;
cnt --;
}
ans += str[i];
}
while(cnt){
ans += p;
cnt --;
}
return ans;
}
};
500
这题画一下图就搞定了,如果一个边的双连通图中的点被选为M点集,那么怎么搞都能形成一个连通图。加入一个边的双连通块中的点有 cnt 个点,那么共可以形成的点集的方式有 2cnt 个。如果不是双连通图中的点,那么只有它连接了双连通图上的点,并且双连通图上的点连接到 n 才能够形成。
公式说得比较明白一点吧,假设原始图是一个连通图,那么这个连通图中最多只可能出现一个双连通分量。假设这个双连通分量有
那么共可以形成的点集数量为:
ps: 由于本题可能有重边,所以需要特判一下。
代码:
#include <vector>
#include <list>
#include <map>
#include <set>
#include <deque>
#include <stack>
#include <bitset>
#include <algorithm>
#include <functional>
#include <numeric>
#include <utility>
#include <sstream>
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <cstring>
using namespace std;
typedef long long LL;
typedef vector <int> VI;
typedef pair <int,int> PII;
#define FOR(i,x,y) for(int i = (int)x;i < (int)y;++ i)
#define IFOR(i,x,y) for(int i = (int)x;i > (int)y;-- i)
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define lrt rt<<1
#define rrt rt<<1|1
#define lson rt<<1,l,mid
#define rson rt<<1|1,mid+1,r
const int inf = 1e9+7;
const int N = 55;
int in(){
int ans=0;
char last=' ',ch=getchar();
while(ch<'0' || ch>'9')last=ch,ch=getchar();
while(ch>='0' && ch<='9')ans=ans*10+ch-'0',ch=getchar();
if(last=='-')ans=-ans;
return ans;
}
void out(int a) {
if(a < 0) { putchar('-'); a = -a; }
if(a >= 10) out(a / 10);
putchar(a % 10 + '0');
}
vector <int> G[N];
stack <int> s;
int pos[N],dfn[N],dfs_clock,low[N],n,m,ans,num[N];
void dfs(int u,int fa){
dfn[u] = low[u] = ++dfs_clock;
s.push(u);
FOR(i,0,G[u].size()){
int v = G[u][i];
if(!dfn[v]){
dfs(v,u);
low[u] = min(low[u],low[v]);
}
else if(v != fa){
low[u] = min(dfn[v],low[u]);
}
}
if(low[u] == dfn[u]){
ans++;
int cnt = 0;
while(!s.empty()){
int v = s.top();
cnt ++;
s.pop();
if(v == u) break;
}
num[ans-1] = cnt;
}
}
class Sunnygraphs2
{
public:
long long count(vector <int> a)
{
n = (int)a.size();
FOR(i,0,n) G[i].clear();
memset(dfn,0,sizeof(dfn));
FOR(i,0,n) low[i] = inf;
while(!s.empty()) s.pop();
dfs_clock = 0; ans = 0;
memset(num,0,sizeof(num));
FOR(i,0,n){
int u = a[i];
if(a[u] == i && u < i){
num[ans++] = 2;
continue;
}
G[u].pb(i); G[i].pb(u);
}
FOR(i,0,n){
if(!dfn[i]) dfs(i,-1);
}
int tot = 0,tans = 0;
FOR(i,0,ans) if(num[i] >= 2)
tot += num[i],tans ++;
LL res = 1;
int ress = n-tot;
FOR(i,0,ans){
res *= ((1LL << num[i])-1);
}
res *= (1LL << ress);
if(tans == 1) res ++;
return res;
}
};
900
要求不能整除这个数的数的第二小,很容易想到暴力!!!因为可能出现的答案的值很小,不会超过 30 ,暴力枚举 num 第一个不能被整除的数,第二个不能被整除的数,那么 n 的前缀和,只需要算第一小,第二小,对这个前缀和的贡献就可以了。
感觉这里面有一个不错的东西:如何找出第一小,第二小不能整除整个1…n中数的贡献?能做的是整除,处理不整除只需要搞一个容斥就好了,因为是简单的容斥,所以瞎J8写写就好了!!!
复杂度很容易想到
代码:
#include <vector>
#include <list>
#include <map>
#include <set>
#include <deque>
#include <stack>
#include <bitset>
#include <algorithm>
#include <functional>
#include <numeric>
#include <utility>
#include <sstream>
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <cstring>
using namespace std;
typedef long long LL;
typedef vector <int> VI;
typedef pair <int,int> PII;
#define FOR(i,x,y) for(int i = x;i < y;++ i)
#define IFOR(i,x,y) for(int i = x;i > y;-- i)
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define lrt rt<<1
#define rrt rt<<1|1
#define lson rt<<1,l,mid
#define rson rt<<1|1,mid+1,r
int in(){
int ans=0;
char last=' ',ch=getchar();
while(ch<'0' || ch>'9')last=ch,ch=getchar();
while(ch>='0' && ch<='9')ans=ans*10+ch-'0',ch=getchar();
if(last=='-')ans=-ans;
return ans;
}
void out(int a) {
if(a < 0) { putchar('-'); a = -a; }
if(a >= 10) out(a / 10);
putchar(a % 10 + '0');
}
const int maxn = 30;
LL lcm[maxn][maxn],nd[maxn][maxn][3];
LL Lcm(LL x,LL y) {return x/__gcd(x,y)*y;}
void init(){
lcm[1][1] = 1;
FOR(i,1,maxn) FOR(j,1,maxn) lcm[i][j] = 1;
FOR(i,1,maxn){
lcm[i][i] = i;
FOR(j,i+1,maxn){
LL tem = __gcd(lcm[i][j-1],(LL)j);
lcm[i][j] = lcm[i][j-1]/tem*j;
}
}
FOR(i,2,maxn){
FOR(j,i+1,maxn){
nd[i][j][0] = Lcm(lcm[1][i-1],lcm[i+1][j-1]);
nd[i][j][1] = Lcm(lcm[1][i-1],lcm[i+1][j]);
nd[i][j][2] = lcm[1][j-1];
}
}
}
class Undiv2
{
public:
long long calc(int n){
LL ans = 0;
FOR(i,2,maxn){
FOR(j,i+1,maxn){
LL tem = 0;
tem = j*(n/nd[i][j][0]-n/nd[i][j][1]-n/nd[i][j][2]+n/lcm[1][j]);
ans += tem;
}
}
return ans;
}
long long getsum(int n)
{
init();
return calc(n);
}
};