Justifying the Conjecture

显然,构造一个偶数和一个质数是最方便的,那么直接判断奇偶性选择输出2,n-2还是3,n-3就行,n<6特判

#include<bits/stdc++.h>
#define pb push_back
#define fi first
#define se second
using namespace std;
typedef long long LL;
typedef unsigned long long uLL;
typedef pair<int,int> PII;
typedef pair<LL,LL> PLL;
typedef vector<int> VI;


const int N = 5e3+5;
const int mod = 998244353;
const LL inf = 0x3f3f3f3f3f3f3f3f;
const int maxn = 2e6+6;

int t,n;
int main(){
     scanf("%d",&t);
     while(t--){
        scanf("%d",&n);
        if(n<=5) printf("-1\n");
        else {
            if(n&1) printf("3 %d\n",n-3);
            else printf("2 %d\n",n-2);
        }
     }
}

Fixing Banners

枚举每个字符串对应"harbin"中的哪个字符就行

#include<bits/stdc++.h>
#define pb push_back
#define fi first
#define se second
using namespace std;
typedef long long LL;
typedef unsigned long long uLL;
typedef pair<int,int> PII;
typedef pair<LL,LL> PLL;
typedef vector<int> VI;


const int N = 5e3+5;
const int mod = 998244353;
const LL inf = 0x3f3f3f3f3f3f3f3f;
const int maxn = 2e6+6;

int t,n,mp[10][10],a[10];
char s[maxn];
int main(){
     scanf("%d",&t);
     while(t--){
        for(int i=1;i<=6;i++){
            scanf("%s",s+1);
            n=strlen(s+1);
            for(int j=1;j<=n;j++){
                if(s[j]=='h')  mp[i][1]=1;
                if(s[j]=='a')  mp[i][2]=1;
                if(s[j]=='r')  mp[i][3]=1;
                if(s[j]=='b')  mp[i][4]=1;
                if(s[j]=='i')  mp[i][5]=1;
                if(s[j]=='n')  mp[i][6]=1;
            }
            a[i]=i;
        }
        int ans=0;
        do{
            int flag=0;
            for(int i=1;i<=6;i++){
                if(!mp[a[i]][i]){
                    flag=1;break;
                }
            }
            if(!flag) {
                //for(int i=1;i<=6;i++) cout<<a[i]<<',';cout<<'\n';
                ans=1;break;
            }
        }while(next_permutation(a+1,a+1+6));
        if(ans) printf("Yes\n");
        else printf("No\n");
        for(int i=1;i<=6;i++) for(int j=1;j<=6;j++)
            mp[i][j]=0;
     }
}

Keeping Rabbits

s b 公式题,手算一下k=1的情况就能发现规律

#include<bits/stdc++.h>
#define pb push_back
#define fi first
#define se second
using namespace std;
typedef long long LL;
typedef unsigned long long uLL;
typedef pair<int,int> PII;
typedef pair<LL,LL> PLL;
typedef vector<int> VI;


const int N = 5e3+5;
const int mod = 998244353;
const LL inf = 0x3f3f3f3f3f3f3f3f;
const int maxn = 2e6+6;

int n,t;
double k,w[maxn],sum;
int main(){
     scanf("%d",&t);
     while(t--){
        sum=0;
        scanf("%d%lf",&n,&k);
        for(int i=1;i<=n;i++){
            scanf("%lf",&w[i]);
            sum+=w[i];
        }
        for(int i=1;i<=n;i++){
            if(i!=1) printf(" ");
            printf("%f",1.0*(k+sum)*w[i]/sum);
        }
     printf("\n");
     }
}

Interesting Permutation

好题,H[i]的合法状态为非减的序列,并且h1=0,hn=n-1;
通过观察可以发现,hi可以看作一个min,max构成的区间
那么,
①hi>hi-1 相当于区间长度增加,可以选择增加max,或者减小min,两种情况ans*=2;
②hi=hi-1 放区间中剩下的数字,有a[i]+1-(i-1)种情况,即ans*=(a[i]-i+2)

#include<bits/stdc++.h>
#define pb push_back
#define fi first
#define se second
using namespace std;
typedef long long LL;
typedef unsigned long long uLL;
typedef pair<int,int> PII;
typedef pair<LL,LL> PLL;
typedef vector<int> VI;


const int N = 5e3+5;
const int mod =1e9+7;
const LL inf = 0x3f3f3f3f3f3f3f3f;
const int maxn = 2e6+6;
int n,t,a[maxn];
int main(){
     scanf("%d",&t);
     while(t--){
         scanf("%d",&n);
         for(int i=1;i<=n;i++){
            scanf("%d",&a[i]);
         }
         int flag=0;
         for(int i=1;i<=n;i++){
            if(a[i]<a[i-1]) flag=1;
            if(a[i]==0&&i!=1) flag=1;
            if(a[i]>n-1) flag=1;
            if(flag) break;
         }
         if(flag||a[1]!=0||a[n]!=n-1) {printf("0\n");continue;}

         LL ans=1,cnt;
         for(int i=2;i<=n;i++){
            if(a[i]!=a[i-1]) ans=ans*2%mod,cnt=a[i]-i+1;
            else {
                ans=ans*cnt%mod;
                cnt--;
            }
         }
         printf("%lld\n",ans);
     }
}

Exchanging Gifts

好题但是题意有点迷,多给了一个条件?
1️⃣先考虑怎么样安排数字能使答案最优:按每个数字出现的次数排序后,先不考虑次数最多的数字,然后在从大到小将当前次数的数字放填入次数最大且未被填满的数字里(一定能填完),然后剩下的位置放次数最多的数字。
所以当sum-max<max时ans=sum-(max-(sum-max))
否则ans=sum
sum为所有数字出现次数和,max为最大次数
2️⃣统计Sn 的 sum 和 max,直接转移每个数字很难,考虑以序列为单位转移,算出Sn由哪些序列出现多少次后,在挨个计算。并且第i个序列只能由1~i-1转移过来,所以我们直接倒着DP就好,然后用MAP统计max

#include<bits/stdc++.h>
#include<ext/pb_ds/assoc_container.hpp>
#include<ext/pb_ds/hash_policy.hpp>
using namespace __gnu_pbds;
#define pb push_back
#define fi first
#define se second
using namespace std;
typedef long long LL;
typedef unsigned long long uLL;
typedef pair<int,int> PII;
typedef pair<LL,LL> PLL;
typedef vector<int> VI;


const int N = 5e3+5;
const int mod =1e9+7;
const LL inf = 0x3f3f3f3f3f3f3f3f;
const int maxn = 1e6+6;

int _,n,op[maxn][3];
LL dp[maxn],c[maxn];
VI G[maxn];
gp_hash_table<int,int> mp;
inline char nc() {
    static char buf[100000], *p1 = buf, *p2 = buf;
    return p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 100000, stdin), p1 == p2) ? EOF : *p1++;
}

inline int read() {
    char ch = nc(); int sum = 0;
    while (!(ch >= '0' && ch <= '9')) ch = nc();
    while (ch >= '0' && ch <= '9') sum = sum * 10 + ch - 48, ch = nc();
    return sum;
}
int main(){
    for(_=read();_;_--){
        n=read();
        for(int i=1;i<=n;i++){
            op[i][0]=read();
            if(op[i][0]==1){
                int k;k=read();
                G[i].clear();
                for(int j=0,d;j<k;j++) d=read(),G[i].pb(d);
            }
            else op[i][1]=read(),op[i][2]=read();
            dp[i]=0;
        }
        dp[n]=1;
        for(int i=n;i>=1;i--){
            if(op[i][0]==2){
                for(int j=1;j<=2;j++) dp[op[i][j]]+=dp[i];
            }
        }

        LL sum=0,ma=0,cnt=0;
        for(int i=1;i<=n;i++) if(op[i][0]==1&&dp[i]){
            sum+=1ll*dp[i]*G[i].size();
            for(int j:G[i]){
                if(mp[j]) ma=max(ma,c[mp[j]]+=dp[i]);
                else mp[j]=++cnt,ma=max(ma,c[cnt]+=dp[i]);
            }
        }
        //printf("%lld %lld\n",sum,ma);
        if(sum-ma<ma) printf("%lld\n",2*sum-2*ma);
        else printf("%lld\n",sum);
        mp.clear();for(int i=1;i<=cnt;i++) c[i]=0;
    }
}
 

Binary Numbers

分析后i只和i-1,i+1有关,然后dp,注意细节
完全是看题解做出来的,很有挑战性

#include<bits/stdc++.h>

#define pb push_back
#define fi first
#define se second
using namespace std;
typedef long long LL;
typedef unsigned long long uLL;
typedef pair<int,int> PII;
typedef pair<LL,LL> PLL;
typedef vector<int> VI;


const int N = 5e3+5;
const int mod =1e8+7;
const LL inf = 0x3f3f3f3f3f3f3f3f;
const int maxn = 1e6+6;

int _,n,m;
int l[maxn],r[maxn];
LL dp[131100][20][20];
int calu(int a, int b)
{
	int res = 0;
	for(int i=m-1; i>=0; --i)
	{
		if((a>>i&1)==(b>>i&1)) ++res;
		else break;
	}
	return res;
}
inline int read(){
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9') {if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}


int main(){

    for(_=read();_;_--){
        m=read();n=read();
        for(int i=1;i<=n;i++){
            l[i]=read();r[i]=read();
        }
        memset(dp,0,(n+1)*sizeof dp[0]);

        LL ans=0;
        for(int i=1;i<=n;i++){
            for(LL a=l[i];a<=r[i];a++){
                int downj=calu(a,r[i-1]);
                int upk=calu(a,l[i]);
                LL sum=0;
                if(i>1)
                for(int j=downj;j<=m;j++){
                    for(int k=0;k<=upk;k++){
                        sum+=dp[i-1][j][k];sum%=mod;
                    }
                }
                if(i==1) sum=1;
                if(i==n) {ans=(ans+sum*a%mod)%mod;continue;}

                downj=calu(a,r[i]);
                upk=calu(a,l[i+1]);
                dp[i][downj][upk]+=sum*a%mod;
                dp[i][downj][upk]%=mod;
            }
        }

        printf("%lld\n",ans);
    }
}


Artful Paintings补

LRU Algorithm补