Hetui

A:

四维的01背包,注意一下所有代价都是0时的方案输出即可

#include<queue>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>

#define maxn 37

using namespace std;

int p[maxn],a[maxn],c[maxn],m[maxn],g[maxn];
int dp[maxn][maxn][maxn][maxn],use[maxn];
int n,P,A,C,M;

vector <int> mem;

int main(){
    scanf("%d",&n);
    int cnt=0;

    for(int i=1;i<=n;i++)
    {
        scanf("%d%d%d%d%d",&p[i],&a[i],&c[i],&m[i],&g[i]);
        if(p[i]==0&&a[i]==0&&c[i]==0&&m[i]==0)
        {
            mem.push_back(i);
            use[i]=1;
        }
    }
    scanf("%d%d%d%d",&P,&A,&C,&M);
    dp[0][0][0][0]=0;
    for(int i=1;i<=n;i++){
        if(use[i]==1) continue;
        for(int j=P;j>=0;j--)
            for(int k=A;k>=0;k--)
                for(int t=C;t>=0;t--)
                    for(int l=M;l>=0;l--)
                        if(j>=p[i] && k>=a[i] && t>=c[i] && l>=m[i]){
                            if(dp[j][k][t][l]<dp[j-p[i]][k-a[i]][t-c[i]][l-m[i]]+g[i]){
                                dp[j][k][t][l]=dp[j-p[i]][k-a[i]][t-c[i]][l-m[i]]+g[i];
                            }
                        }
    }
    int ans=0,l1=P,l2=A,l3=C,l4=M;
    for(int j=P;j>=0;j--)
            for(int k=A;k>=0;k--)
                for(int t=C;t>=0;t--)
                    for(int l=M;l>=0;l--)
                        if(dp[j][k][t][l]>=ans){
                            l1=j; l2=k; l3=t; l4=l;
                            ans=dp[j][k][t][l];
                        }

    while(1){
        int t=233;
        for(int i=1;i<=n;i++)
            if(!(p[i]==0 && a[i]==0 && c[i]==0 && m[i]==0) && !use[i] && l1>=p[i] && l2>=a[i] && l3>=c[i] && l4>=m[i] && dp[l1][l2][l3][l4]==dp[l1-p[i]][l2-a[i]][l3-c[i]][l4-m[i]]+g[i]){
                use[i]=1; t=i; break;
            }
        if(t==233) break;
        mem.push_back(t);
        l1-=p[t]; l2-=a[t]; l3-=c[t]; l4-=m[t];
    }
    printf("%d\n",mem.size());
    for(int i=0;i<mem.size();i++)
        printf("%d ",mem[i]-1);
    return 0;
}
View Code

C:

 

E:

 

#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <vector>
#include <string>
#include <map>
#include <unordered_map>
#define LSON l,m,x<<1
#define RSON m+1,r,x<<1|1
using namespace std;

const int MAX=2e6+5;
const unsigned long long base = 163;
char s[MAX];
unsigned long long p[MAX],hh[MAX];
unordered_map<unsigned long long,int> mp;
int cnt;
vector<int> L[MAX];

void init(){//处理hh值
    p[0] = 1;
    hh[0] = 0;
    int n = strlen(s + 1);
    for(int i = 1; i < MAX/2; i ++) p[i] =p[i-1] * base;
    for(int i = 1; i <= n; i ++) hh[i] = hh[i - 1] * base + (s[i] - 'a');
}

inline unsigned long long get(int l, int r){//取出g里l - r里面的字符串的hh值
    return hh[r] - hh[l - 1] * p[r - l + 1];
}

inline string read()//inline继续加快速度
{
    char ch=getchar();
    string st1="";
    while (!((ch>='a')&&(ch<='z')))//把前面没用的东西去掉,当然,ch在什么范围内可以依据需要修改
      ch=getchar();
    while ((ch>='a')&&(ch<='z'))
      st1+=ch,ch=getchar();
    return st1;//返回
}//在主程序内可以写st=read(),这样子要读的字符串就到了st内

int main(){
    int i,j; char ch;
    i=0;
    while((ch=getchar())!=EOF){
        s[++i]=ch;
    }
    if(s[i]=='\n') i--;
    int n=i;
    for(i=n+1;i<=2*n;i++)
        s[i]=s[i-n];
    init();
    for(i=1;i<=n;i++){
        unsigned long long h=get(i,i+n-1);
        if(!mp[h]){
            mp[h]=++cnt;
            L[cnt].push_back(i-1);
        }
        else
            L[mp[h]].push_back(i-1);
    }
    printf("%d\n",cnt);
    for(i=1;i<=cnt;i++){
        int size=L[i].size();
        printf("%d ",size);
        for(j=0;j<size;j++){
            printf("%d%c",L[i][j],j==size-1?'\n':' ');
        }
    }
    return 0;
}
View Code

H:

随便推推公式就好,发现和小于n/num的质数数量有关,求一求质数数量的前缀和

#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <vector>
#include <string>
#include <map>
using namespace std;

int pri[6000010], cnt;
bool flag[10000010];
long long sum[10000010];

void init()
{
    cnt=0;
    for(int i = 2; i <= 10000000; i ++)
    {
        if(!flag[i])
        {
            pri[cnt ++] = i;
            flag[i] = 1;
        }
        for(int j = 0; j < cnt && i * pri[j] <= 10000000; j ++)
        {
            flag[i * pri[j]] = 1;
            if(i % pri[j] == 0)
            {
                break;
            }
        }
    }
}

int main()
{
    int i;
    init();
    for(i=0;i<cnt;i++) sum[pri[i]]++;
    for(i=0;i<=10000000;i++) sum[i]+=sum[i-1];
    int n;
    scanf("%d",&n);
    long long ans=0;
    for(i=1;i<=n;i++)
    {
        ans+=sum[n/i]*(sum[n/i]-1);
    }
    printf("%lld\n",ans);
    return 0;
}
View Code

 

I:

 

J:

 

分类:

技术点:

相关文章: