A
签到
#include <iostream>
using namespace std;
#define int long long
int num[9];
signed main() {
freopen("auxiliary.in","r",stdin);
freopen("auxiliary.out","w",stdout);
int n;
cin >> n;
int t = n/3;
int ans = 0;
if (n%3==1) {
ans = 4;
t--;
} else if (n%3==2) {
ans = 1;
}
cout << t*7+ans << "\n";
return 0;
}
B
签到
#include <iostream>
#include <string>
using namespace std;
using ll = long long;
bool exi[255][2];
int main() {
freopen("boolean.in", "r", stdin);
freopen("boolean.out", "w", stdout);
string s;
cin >> s;
int n = s.size(), i = 0;
while (i<n) {
int flag = 0;
if (s[i]=='~') flag = 1, i++;
exi[s[i++]][flag] = 1;
}
ll ans = 1;
int cnt1 = 0, cnt2 = 0;
for (int i = 'a'; i<='z'; ++i) {
if (exi[i][0]^exi[i][1]) cnt1++;
else if (exi[i][0]) cnt2++;
}
for (int i = 'A'; i<='Z'; ++i) {
if (exi[i][0]^exi[i][1]) cnt1++;
else if (exi[i][0]) cnt2++;
}
ans = 1ll<<cnt1;
if (cnt2==0) ans--;
ans*=1ll<<cnt2;
cout << ans ;
return 0;
}
C
签到
#include <iostream>
#include <string>
using namespace std;
using ll = long long;
bool exi[255][2];
int main() {
freopen("boolean.in", "r", stdin);
freopen("boolean.out", "w", stdout);
string s;
cin >> s;
int n = s.size(), i = 0;
while (i<n) {
int flag = 0;
if (s[i]=='~') flag = 1, i++;
exi[s[i++]][flag] = 1;
}
ll ans = 1;
int cnt1 = 0, cnt2 = 0;
for (int i = 'a'; i<='z'; ++i) {
if (exi[i][0]^exi[i][1]) cnt1++;
else if (exi[i][0]) cnt2++;
}
for (int i = 'A'; i<='Z'; ++i) {
if (exi[i][0]^exi[i][1]) cnt1++;
else if (exi[i][0]) cnt2++;
}
ans = 1ll<<cnt1;
if (cnt2==0) ans--;
ans*=1ll<<cnt2;
cout << ans ;
return 0;
}
D
unsolved
E
两种策略,一种是直接搞出lcm,然后剩余数字都可以贪心了。
一种是贪心的把所有不用搞lcm就能合并的数字合并了,即优先那些是因子的数。
然后两种策略每个位置取min输出
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define inf 0x3f3f3f3f
#define mod 1000000007
#define pb push_back
typedef pair<int,int> pir;
string sstr[]={"NO\n","YES\n"};
const int N=1000010;
class node
{
public:
int num;
int x;
bool operator<(node n1)const{
if(num!=n1.num) return num<n1.num;
else return x<n1.x;
}
};
int T,n,m;
map<int,int> mp;
int a[N];
int vec[N];
int dp[N];
int has[N];
int ans1[N],ans2[N];
int ap=0;
set<node> st;//维护块
vector<int> mi;
void add1(int x)
{
for(int i=ap;i<ap+x-1;i++){
ans1[i]=ans1[i-1];
}
ans1[ap+x-1]=ans1[ap+x-2]-1;
ap=ap+x;
}
void add2(int x)
{
for(int i=ap;i<ap+x-1;i++){
ans2[i]=ans2[i-1];
}
ans2[ap+x-1]=ans2[ap+x-2]-1;
ap=ap+x;
}
signed main()
{
freopen("equal.in","r",stdin);
freopen("equal.out","w",stdout);
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i];
mp[a[i]]++;
}
for(auto it:mp){
has[it.first]=it.second;
}
for(int i=1;i<=N;i++){//每个数字
if(!has[i]) continue;
for(int j=2*i;j<N;j+=i){
if(has[j]){//之前的点如果有匹配显然不能合并
//之前的点没有匹配,留着的话可以合并,如果变成inf显然也可以
dp[i]=j;
break;
}
}
if(dp[i]==0) vec[has[i]]++;//数字数量为has[i]时,会剩下位置i
}
st.clear();
for(auto it:mp){
has[it.first]=it.second;
st.insert(node{it.second,it.first});
}
ans1[ap++]=st.size();
while(!st.empty()){
int num=st.begin()->num;
int cnt=0;
while(!st.empty()&&st.begin()->num==num){
st.erase(st.begin());
cnt++;
}
cnt-=vec[num];//共有vec[num]个无法合并
for(int i=0;i<vec[num];i++) mi.pb(num);
for(int i=0;i<cnt;i++) add1(num);
}
if(mi.size()>=2){
add1(mi[0]+mi[1]);
for(int i=2;i<mi.size();i++){
add1(mi[i]);
}
}
mi.clear();
ap=0;
st.clear();
for(auto it:mp){
has[it.first]=it.second;
st.insert(node{it.second,it.first});
}
ans2[ap++]=st.size();
while(!st.empty()){
int num=st.begin()->num;
int cnt=0;
while(!st.empty()&&st.begin()->num==num){
st.erase(st.begin());
cnt++;
}
cnt-=vec[num];
for(int i=0;i<vec[num];i++) mi.pb(num);
for(int i=0;i<cnt;i++) add2(num);
if(mi.size()>=2){
add2(mi[0]+mi[1]);
for(int i=2;i<mi.size();i++){
add2(mi[i]);
}
while(!st.empty()){
auto tmp=st.begin()->num;
st.erase(st.begin());
add2(tmp);
}
}
}
for(int i=0;i<=n;i++) cout<<max(min(ans1[i],ans2[i]),1)<<' ';
}
/*
8
1 1 2 2 4 4 8 9
*/
F
unsolved,待补
G
tarjan,维护从当前点能到达的最low的点和次low的点,如果次low的点比当前点编号更小,说明有两条返祖边,说明可行,起点为当前点,终点为low2。还需要打印路径。因此额外维护返祖边的末端点。
参考链接:https://blog.csdn.net/ME495/article/details/83050131
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define inf 0x3f3f3f3f
#define pb push_back
const int N=200010;
int T,n,m;
int s,t;
vector<int> vec[N];
int low1[N],p1[N],low2[N],p2[N],dfn[N],fa[N],num[N];
int idx;
bool flag;
int vis[N];
queue<int> q;
vector<int> ans;
void upd(int x,int lo,int y)
{
if(lo<low1[x]){
low2[x]=low1[x];
p2[x]=p1[x];
low1[x]=lo;
p1[x]=y;
}
else if(lo<low2[x]){
low2[x]=lo;
p2[x]=y;
}
}
void printans()
{
cout<<ans.size();
for(auto it:ans) cout<<' '<<it;
cout<<'\n';
ans.clear();
}
void print(int x,int t)
{
cout<<s<<' '<<t<<'\n';
int cur=s;
//第一条
ans.pb(s);
while(cur!=t){
cur=fa[cur];
ans.pb(cur);
}
printans();
cur=p2[s];
ans.pb(t);
ans.pb(cur);
while(cur!=s){
cur=fa[cur];
ans.pb(cur);
}
reverse(ans.begin(),ans.end());
printans();
cur=t;
ans.pb(t);
while(cur!=num[low1[x]]){
cur=fa[cur];
ans.pb(cur);
}
cur=p1[s];
ans.pb(cur);
while(cur!=s){
cur=fa[cur];
ans.pb(cur);
}
reverse(ans.begin(),ans.end());
printans();
}
void tarjan(int x,int pa)
{
dfn[x]=low1[x]=low2[x]=++idx;
num[idx]=x;
for(auto j:vec[x]){
if(j==pa) continue;
if(dfn[j]&&dfn[j]<dfn[x]){
upd(x,dfn[j],x);
}
else if(dfn[j]==0){
fa[j]=x;
tarjan(j,x);
upd(x,low1[j],p1[j]);
}
}
if(!flag&&low2[x]<dfn[x]){
flag=1;
s=x;
t=num[low2[x]];
print(s,t);
}
}
signed main()
{
freopen("grand.in","r",stdin);
freopen("grand.out","w",stdout);
cin>>T;
while(T--){
cin>>n>>m;
idx=flag=0;
for(int i=0;i<=2*max(m,n);i++){
vec[i].clear();
dfn[i]=fa[i]=0;
low1[i]=low2[i]=inf;
p1[i]=p2[i]=vis[i]=0;
num[i]=0;
}
for(int i=1;i<=m;i++){
int u,v;
cin>>u>>v;
vec[u].pb(v);
vec[v].pb(u);
}
for(int i=1;i<=n;i++){
if(dfn[i]==0){
tarjan(i,i);
}
}
if(!flag){
cout<<-1<<'\n';
}
}
}
/*
100
5 6
1 2
2 3
1 3
1 4
4 3
3 5
6 8
2 3
3 1
4 1
1 2
3 4
4 5
6 4
6 5
*/
H
dp每个无父亲的子树中空闲节点,以及根结点是否可能空闲。
然后贪心的优先将空闲节点多的子树加入1所在的子树中,如果之前有空闲节点且根空闲,那么可以匹配。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define inf 0x3f3f3f3f
#define mod 1000000007
#define pb push_back
typedef pair<int,int> pir;
string sstr[]={"NO\n","YES\n"};
const int N=200010;
class node
{
public:
vector<int> fre;
int is;//根结点是否空闲
int id;
bool operator<(node n1)const{
if(id==1||n1.id==1) return id<n1.id;
else if(fre.size()!=n1.fre.size()) return fre.size()>n1.fre.size();
else if(is!=n1.is) return is<n1.is;
else return id<n1.id;
}
}no[N];
int T,n,m;
int dp[N][2];
vector<int> vec[N];
int p[N];
int cnt=0;
deque<int> cfre;
void dfs(int x,int rt)
{
int sum=0;
vector<int> tmp;
for(auto j:vec[x]){
dfs(j,rt);
if(dp[j][0]==dp[j][1]) tmp.pb(j);//优先把上面的留下
sum+=dp[j][1];
}
if(tmp.empty()){//当前节点空下
dp[x][0]=dp[x][1]=sum;
if(x==rt) no[cnt].is=1;
}
else{
dp[x][0]=dp[x][1]=sum;
dp[x][1]++;
for(int i=1;i<tmp.size();i++) no[cnt].fre.pb(tmp[i]);
}
}
signed main()
{
freopen("hidden.in","r",stdin);
freopen("hidden.out","w",stdout);
cin>>n;
for(int i=2;i<=n;i++){
cin>>p[i];
if(p[i]) vec[p[i]].pb(i);
}
int ans=0;
for(int i=1;i<=n;i++){
if(p[i]==0){
dfs(i,i);
no[cnt].id=i;
cnt++;
ans+=dp[i][1];
//cout<<"|||"<<i<<' '<<ans<<' '<<cnt<<' '<<no[cnt-1].id<<' '<<no[cnt-1].is<<' '<<no[cnt-1].fre.size()<<'\n';
}
}
sort(no,no+cnt);
assert(no[0].id==1);
int pre=0;
if(no[0].is) cfre.pb(1);
for(auto it:no[0].fre) cfre.pb(it);
int cp=0;
for(int i=1;i<cnt;i++){
if(no[i].is){//空闲
if(!cfre.empty()){
int tmp=cfre.front();
cfre.pop_front();
p[no[i].id]=tmp;
ans++;
}
else cfre.pb(no[i].id),p[no[i].id]=1;//当前根考虑和后面的匹配
}
else p[no[i].id]=1;//不空闲,直接和1连即可
for(auto it:no[i].fre) cfre.pb(it);
}
cout<<ans<<'\n';
for(int i=2;i<=n;i++) cout<<p[i]<<' ';
}
/*
10
0 0 0 0 0 0 0 0 0
*/
I
签到
#include <iostream>
#include <vector>
#include <string>
using namespace std;
int nums[2000106];
const int N = 1e6+7;
struct Edge {
int l, r;
};
int main() {
freopen("intel.in", "r", stdin);
freopen("intel.out", "w", stdout);
ios::sync_with_stdio(false);
int n, x, y, lastx, lasty;
cin >> n;
cin >> lastx >> lasty;
int prex = lastx, prey = lasty;
vector<Edge> v1, v2;
for (int i = 1; i<n; ++i) {
cin >> x >> y;
if (x==lastx) {
int l = y, r = lasty;
if (l>r) swap(l, r);
r--;
v1.push_back({l, r});
} else {
int l = x, r = lastx;
if (l>r) swap(l, r);
r--;
v2.push_back({l, r});
}
lastx = x, lasty = y;
}
if (x==prex) {
int l = y, r = prey;
if (l>r) swap(l, r);
r--;
v1.push_back({l, r});
} else {
int l = x, r = prex;
if (l>r) swap(l, r);
r--;
v2.push_back({l, r});
}
long long ans = 0;
for (auto &[l, r]:v1) {
nums[l+N]++, nums[r+N+1]--;
}
// ans+=nums[0];
for (int i = 1; i<2000106; ++i) {
nums[i]+=nums[i-1];
if (nums[i]>2) ans+=nums[i]-2;
}
for (int i = 0; i<2000106; ++i) nums[i] = 0;
for (auto &[l, r]:v2) {
nums[l+N]++, nums[r+N+1]--;
}
for (int i = 1; i<2000106; ++i) {
nums[i]+=nums[i-1];
if (nums[i]>2) ans+=nums[i]-2;
}
cout << ans;
return 0;
}
K
签到
#include <iostream>
#include <vector>
#include <string>
using namespace std;
int main() {
freopen("kotlin.in", "r", stdin);
freopen("kotlin.out", "w", stdout);
int h, w, n;
cin >> h >> w >> n;
int nh, nw;
nh = (h+1)/2, nw = (w+1)/2;
int i = 1, j = 1;
for (i = 1; i<=nh; ++i) {
for (j = 1; j<=nw; ++j) {
if (j*i==n) goto P;
}
}
P: {}
if (i*j==n) {
// cout << i << "\n";
i--, j--;
vector<string> g(h, string(w, '.'));
for (int t = 1; t<=i; ++t) {
g[t*2-1] = string(w, '#');
}
for (int t = 1; t<=j; ++t) {
for (int k = 0; k<h; ++k) {
g[k][t*2-1] = '#';
}
}
for (string &t:g) {
cout << t << "\n";
}
} else {
cout << "Impossible\n";
}
return 0;
}
L
(队友做的
#include<iostream>
#include<cmath>
#include<algorithm>
#include<string.h>
#include<vector>
#define lint int64_t
#define bint __int128
using
namespace
std;
lint n;
vector<vector<lint>> kotae;
bint qow(bint a,int b){
bint ans=1;
for(;b;a=a*a,b>>=1){
if(b&1){
ans=ans*a;
if(ans>2e18) return 2e18;
}
}
if(ans>2e18) return 2e18;
return ans;
}
bint cal(bint p,int sz,int k){
return qow(p,sz-k)*qow(p+1,k);
}
void check(int sz,int k){
//cout<<"checking "<<sz<<' '<<k<<endl;
bint l=2,r=pow(10,18./sz)*2.,mid;
while(l<r){
mid=(l+r)>>1;
if(cal(mid,sz,k)<n){
l=mid+1;
}
else{
r=mid;
}
}
if(cal(l,sz,k)==n){
vector<lint> tem;
for(int i=0;i<sz;i++){
tem.push_back((lint)(i<sz-k?l:l+1));
}
kotae.push_back(tem);
//printf("hit\n");
}
else{
//printf("failed, l=%lld, ans=%lld\n",(lint)l,(lint)cal(l,sz,k));
}
}
signed main(){
freopen("little.in","r",stdin);
freopen("little.out","w",stdout);
scanf("%lld",&n);
if(__builtin_popcountll(n)==1){
printf("-1\n");
return EOF+1;
}
vector<lint> tem;
tem.push_back(n);
kotae.push_back(tem);
lint l=1,r=2e9,mid;
while(l<r){
mid=(l+r)>>1;
if(mid*mid<n){
l=mid+1;
}
else{
r=mid;
}
}
if(l*l==n){
tem.clear();
tem.push_back(l);
tem.push_back(l);
kotae.push_back(tem);
}
l=1,r=2e9,mid;
while(l<r){
mid=(l+r)>>1;
if(mid*(mid+1)<n){
l=mid+1;
}
else{
r=mid;
}
}
if(l*(l+1)==n){
tem.clear();
tem.push_back(l);
tem.push_back(l+1);
kotae.push_back(tem);
}
int limit=log2(n)+1;
for(int sz=3;sz<=limit;sz++){
for(int k=0;k<sz;k++){
check(sz,k);
}
}
printf("%u\n",kotae.size());
for(vector<lint>& item:kotae){
printf("%u",item.size());
for(lint& it:item){
printf(" %lld",it);
}
printf("\n");
}
end:
return EOF+1;
}
/*
996491789294632962
999999999999999989
3754371689208
20
1000000000000000000
*/