D. Colored Rectangles,C-Rolling Girl 

84 阅读1分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 18 天,点击查看活动详情

Problem - D - Codeforces

 又是看数据过的一题,,,

一开始看这题数据那么小感觉像是dp的,但是感觉贪心也可以过,于是就开了三个优先队列乱搞了一下就交了,果断wa6,之后一直没想出哪里错但是已经知道这个方法必定是有纰漏的,可能是三个队列中数的选择出现了冲突,实在想不出来就去看数据了(可恶啊),发现果然是选择的方式也是会影响答案,所以只能老实去dp了,dp[i][j][k]表示选了i个r,j个g,k个b所能获得的最大面积,然后转移方程也很好列;

#define endl '\n'
#define double long double
using namespace std;
const int mod=1e9+7;
const int inf=3e18;
int R,G,B,r[205],g[205],b[205],dp[205][205][205];
signed main()
{
    cin.tie(0);cout.tie(0);ios::sync_with_stdio(0);
    //freopen("in.txt", "r", stdin);
    cin>>R>>G>>B;
    for(int i=1;i<=R;i++) cin>>r[i];
    for(int i=1;i<=G;i++) cin>>g[i];
    for(int i=1;i<=B;i++) cin>>b[i];
    sort(r+1,r+R+1,cmp);
    sort(g+1,g+G+1,cmp);
    sort(b+1,b+B+1,cmp);
    memset(dp,0,sizeof(dp));
    int ans=0;
    for(int i=0;i<=R;i++)
        for(int j=0;j<=G;j++)
            for(int k=0;k<=B;k++)
            {
                if(i&&j) dp[i][j][k]=max(dp[i][j][k],dp[i-1][j-1][k]+r[i]*g[j]);
                if(i&&k) dp[i][j][k]=max(dp[i][j][k],dp[i-1][j][k-1]+r[i]*b[k]);
                if(j&&k) dp[i][j][k]=max(dp[i][j][k],dp[i][j-1][k-1]+g[j]*b[k]);
                ans=max(ans,dp[i][j][k]);
            }
    cout<<ans<<endl;
    return 0;
}

C-Rolling Girl 

在思考了一堆假思路后终于想出来了,但是由于害怕复杂度就没敢敲,最后还是估了下复杂度一看发现还不到1e8,顿时信心满满,然后T了,,,__gcd()是2*log(max(a,b)),承受不起,最后做了一点小优化就过了

假设从n离开再回到n算一轮,可以发现当距离为i时,一轮需要走n/__gcd(i,n)步,走的点都是__gcd(i,n)的倍数,答案ans[i]就是这些倍数点中的最小值乘以一轮的步数,最小值就是需要走的轮数,所以预处理出n的因数后再去求这些因数的倍数的点数的最小值就可以线性算出来了

const int p=1004535809;
unsigned seed, mod;
unsigned read() {
    seed ^= seed << 13;
    seed ^= seed >> 5;
    seed ^= seed << 7;
    return seed % mod + 1;
}
const int N=1e7+7;
int n,a[N],g[N];
vector<int>v;
int mp[N];
signed main()
{
    cin.tie(0);cout.tie(0);ios::sync_with_stdio(0);
    //freopen("in.txt", "r", stdin);
    cin>>n>>seed>>mod;
    for(int i=1;i<=n;i++) a[i]=read(),g[i]=1;
    for(int i=1;i*i<=n;i++)
    {
        if(n%i==0)
        {
            v.push_back(i);
            if(n/i!=i) v.push_back(n/i);
        }
    }
    sort(v.begin(),v.end());
    for(int i=0;i<v.size();i++)
    {
        int x=v[i];
        mp[x]=inf;
        for(int j=x;j<=n;j+=x)
        {
            mp[x]=min(mp[x],a[j]);
            if(n%x==0) g[j]=x;//求gcd的小优化,n和j都是x的倍数,并且x是不断递增的,所以这样枚举不会错
        }
    }
    int ans=0;
    for(int i=1;i<=n;i++)
    {
        int x=g[i];
        int y=n/x;
        ans=(ans+mp[x]*y%p)%p;
    }
    cout<<ans<<endl;
    return 0;
}