2016 CCPC Hangzhou Onsite

A:题意:n个格子排成一排,每个a[i],要求重排成k个,每个人数相同,合并两个和划分成两个(可以不等)都是花费为1,问最小花费

题解:从前往后贪心即可,由于哪个地方忘开ll,wa了,全改成ll就过了

//#pragma comment(linker, "/stack:200000000")
//#pragma GCC optimize("Ofast,no-stack-protector")
//#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
//#pragma GCC optimize("unroll-loops")
#include<bits/stdc++.h>
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define pi acos(-1.0)
#define ll long long
#define vi vector<int>
#define mod 1000000007
#define C 0.5772156649
#define ls l,m,rt<<1
#define rs m+1,r,rt<<1|1
#define pil pair<int,ll>
#define pli pair<ll,int>
#define pii pair<int,int>
#define cd complex<double>
#define ull unsigned long long
#define base 1000000000000000000
#define fio ios::sync_with_stdio(false);cin.tie(0)

using namespace std;

const double eps=1e-6;
const int N=100000+10,maxn=5000+10,inf=0x3f3f3f3f,INF=0x3f3f3f3f3f3f3f3f;

ll a[N],n,k;
void solve(ll x)
{
    ll ans=0,res=0;
    for(int i=1;i<=n;i++)
    {
        if(res!=0)ans++,a[i]+=res;
        if(a[i]>=x)
        {
            ll te=a[i]/x;
            if(a[i]%x==0)te--;
            ans+=te;
            res=a[i]%x;
        }
        else res=a[i];
    }
    printf("%lld\n",ans);
}
int main()
{
    int T;scanf("%d",&T);
    for(int _=1;_<=T;_++)
    {
        scanf("%lld%lld",&n,&k);
        ll sum=0;
        for(int i=1;i<=n;i++)
        {
            scanf("%lld",&a[i]);
            sum+=a[i];
        }
        printf("Case #%d: ",_);
        if(sum%k!=0)puts("-1");
        else solve(sum/k);
    }
    return 0;
}
/********************

********************/
View Code

B:题意:n个炸弹,引爆需要花费,引爆后会引爆范围内的炸弹,问最小花费

题解:强连通缩点求dag上度数最小的点,(队友写的,细节不清楚)

#include<bits/stdc++.h>
#define LL long long
#define fi first
#define se second
#define mk make_pair
#define pii pair<int,int>
#define piii pair<int,pair<int,int>>

using namespace std;

const int N = 1000 + 7;
const int M = 1e4 + 7;
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9 + 7;

int n, idx, top, cnt, id[N], dfn[N], st[N], low[N], deg[N];
LL cost[N];
bool in[N];


struct Point {
    LL x, y, r, c;
} p[N];

vector<int> edge[N];


void tarjan(int u) {
    st[top++] = u; ++idx;
    low[u] = dfn[u] = idx;
    in[u] = true;

    for(int v : edge[u]) {
        if(!dfn[v]) {
            tarjan(v);
            low[u] = min(low[u], low[v]);
        } else if(in[v]) {
            low[u] = min(low[u], dfn[v]);
        }
    }

    if(low[u] == dfn[u]) {
        cnt++;
        while(1) {
            int now = st[--top];
            in[now] = false;
            id[now] = cnt;
            cost[cnt] = min(cost[cnt], p[now].c);
            if(now == u) break;
        }
    }
}

void init() {
    idx = 0; top = 0; cnt = 0;
    memset(deg, 0, sizeof(deg));
    memset(cost, inf, sizeof(cost));
    memset(dfn, 0, sizeof(dfn));
    memset(in, 0, sizeof(in));
    for(int i = 1; i <= n; i++)
        edge[i].clear();
}

LL dis(LL a, LL b, LL c, LL d) {
    return ((a - c) * (a - c) + (b - d) * (b - d));
}
int main() {
    int T; scanf("%d", &T);
    for(int cas = 1; cas <= T; cas++) {
        init();
        scanf("%d", &n);
        for(int i = 1; i <= n; i++)
            scanf("%lld%lld%lld%lld", &p[i].x, &p[i].y, &p[i].r, &p[i].c);

        for(int i = 1; i <= n; i++) {
            for(int j = 1; j <= n; j++) {
                if(i == j) continue;
                if(dis(p[i].x, p[i].y, p[j].x, p[j].y) <= p[i].r * p[i].r) {
                    edge[i].push_back(j);
                }
            }
        }


        for(int i = 1; i <= n; i++) {
            if(!dfn[i]) tarjan(i);
        }

        for(int u = 1; u <= n; u++) {
            for(int v : edge[u]) {
                if(id[u] != id[v]) {
                    deg[id[v]]++;
                }
            }
        }

        LL ans = 0;

        for(int i = 1; i <= cnt; i++)
            if(deg[i] == 0)
                ans += cost[i];
        printf("Case #%d: ", cas);
        printf("%lld\n", ans);
    }
    return 0;
}
/*
*/
View Code

C:题意:有一辆车,n个记录点,要求车速度只能增加,每次通过记录点的时间为整数,问通过n个记录点的最小时间

题解:把加速看成一瞬间,其他都是匀速,那么有vi=si/ti<=si+1/ti+1,可得ti>=si*ti+1/si+1,从后往前贪心即可

//#pragma comment(linker, "/stack:200000000")
//#pragma GCC optimize("Ofast,no-stack-protector")
//#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
//#pragma GCC optimize("unroll-loops")
#include<bits/stdc++.h>
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define pi acos(-1.0)
#define ll long long
#define vi vector<int>
#define mod 10007
#define C 0.5772156649
#define ls l,m,rt<<1
#define rs m+1,r,rt<<1|1
#define pil pair<int,ll>
#define pli pair<ll,int>
#define pii pair<int,int>
#define cd complex<double>
#define ull unsigned long long
#define base 1000000000000000000
#define fio ios::sync_with_stdio(false);cin.tie(0)

using namespace std;

const double eps=1e-6;
const int N=100000+10,maxn=5000+10,inf=0x3f3f3f3f,INF=0x3f3f3f3f3f3f3f3f;

ll a[N],b[N];
int main()
{
    int T;scanf("%d",&T);
    for(int _=1;_<=T;_++)
    {
        int n;scanf("%d",&n);
        a[0]=0;
        for(int i=1;i<=n;i++)scanf("%lld",&a[i]);
        for(int i=0;i<n;i++)b[i]=a[i+1]-a[i];
        ll ans=1,last=1;
        for(int i=n-2;i>=0;i--)
        {
            int now=b[i]*last/b[i+1];
            if(b[i]*last%b[i+1]!=0)now++;
            last=now;
            ans+=last;
        }
        printf("Case #%d: %lld\n",_,ans);
    }
    return 0;
}
/********************

********************/
View Code

D:题意:f(y,k)代表y的每一位的k次方之和,给你x,k求满足x=f(y,k)-y的对数

题解:折半枚举,把前5位预处理出来,然后枚举后5位算答案

//#pragma comment(linker, "/stack:200000000")
//#pragma GCC optimize("Ofast,no-stack-protector")
//#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
//#pragma GCC optimize("unroll-loops")
#include<bits/stdc++.h>
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define pi acos(-1.0)
#define ll long long
#define vi vector<int>
#define mod 1000000007
#define C 0.5772156649
#define ls l,m,rt<<1
#define rs m+1,r,rt<<1|1
#define pil pair<int,ll>
#define pli pair<ll,int>
#define pii pair<int,int>
#define cd complex<double>
#define ull unsigned long long
#define base 1000000000000000000
#define fio ios::sync_with_stdio(false);cin.tie(0)

using namespace std;

const double g=10.0,eps=1e-12;
const int N=10+10,maxn=1000+10,inf=0x3f3f3f3f,INF=0x3f3f3f3f3f3f3f3f;

int x,kk;
int f[11][11];
map<ll,int>m[10];
void prepare()
{
    for(int i=1;i<=9;i++)
    {
        f[i][0]=1;
        for(int j=1;j<=10;j++)f[i][j]=f[i][j-1]*i;
    }
    for(int kk=1;kk<=9;kk++)
    {
        for(int i=0;i<=99999;i++)
        {
            ll te=0,ii=i,now=100000;
            for(int j=5;j<=9;j++)
            {
                te+=f[ii%10][kk]-(ii%10)*now;
                ii/=10;now*=10ll;
            }
            m[kk][te]++;
        }
    }
}
void solve()
{
    ll ans=0;
    for(int i=0;i<=99999;i++)
    {
        ll te=0,ii=i,now=1;
        for(int j=0;j<=4;j++)
        {
            te+=f[ii%10][kk]-(ii%10)*now;
            ii/=10;now*=10ll;
        }
        if(m[kk].find(x-te)!=m[kk].end())ans+=m[kk][x-te];
    }
    printf("%lld\n",ans-(x==0));
}
int main()
{
    prepare();
    int T;scanf("%d",&T);
    for(int _=1;_<=T;_++)
    {
        scanf("%d%d",&x,&kk);
        printf("Case #%d: ",_);
        solve();
    }
    return 0;
}
/***********************

***********************/
View Code

E:题意:给1到9的每个数字出现次数,你每次选3个数构成x+y=z的等式,问不同的等式最多有多少个

题解:爆搜+剪枝,枚举20种方程,x+y=z,y+x=z算一种,加的时候分开算即可,剪枝:当前方程数+剩余数字数/3<最大答案,剩余方程数+当前方程<最大答案,

//#pragma comment(linker, "/stack:200000000")
//#pragma GCC optimize("Ofast,no-stack-protector")
//#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
//#pragma GCC optimize("unroll-loops")
#include<bits/stdc++.h>
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define pi acos(-1.0)
#define ll long long
#define vi vector<int>
#define mod 1000000007
#define C 0.5772156649
#define ls l,m,rt<<1
#define rs m+1,r,rt<<1|1
#define pil pair<int,ll>
#define pli pair<ll,int>
#define pii pair<int,int>
#define cd complex<double>
#define ull unsigned long long
#define base 1000000000000000000
#define fio ios::sync_with_stdio(false);cin.tie(0)

using namespace std;

const double eps=1e-6;
const int N=1000000+10,maxn=5000+10,inf=0x3f3f3f3f,INF=0x3f3f3f3f3f3f3f3f;

int eq[20][3]={
{1,1,2},
{1,2,3},
{1,3,4},
{1,4,5},
{1,5,6},
{1,6,7},
{1,7,8},
{1,8,9},
{2,2,4},
{2,3,5},
{2,4,6},
{2,5,7},
{2,6,8},
{2,7,9},
{3,3,6},
{3,4,7},
{3,5,8},
{3,6,9},
{4,4,8},
{4,5,9}
};
int a[10],res[20];
void dfs(int a[],int id,int now,int &ans)
{
    int sum=0;
    for(int i=1;i<=9;i++)
    {
        if(a[i]<0)return ;
        else sum+=a[i];
    }
    if(sum/3+now<ans)return ;
    if(res[id]+now<ans)return ;
    if(id==20)
    {
        ans=max(ans,now);
        return ;
    }
    dfs(a,id+1,now,ans);
    if(a[eq[id][0]]>=1&&a[eq[id][1]]>=1&&a[eq[id][2]]>=1)
    {
        a[eq[id][0]]--;a[eq[id][1]]--;a[eq[id][2]]--;
        dfs(a,id+1,now+1,ans);
        a[eq[id][0]]++;a[eq[id][1]]++;a[eq[id][2]]++;
    }
    if(eq[id][0]!=eq[id][1]&&a[eq[id][0]]>=2&&a[eq[id][1]]>=2&&a[eq[id][2]]>=2)
    {
        a[eq[id][0]]-=2;a[eq[id][1]]-=2;a[eq[id][2]]-=2;
        dfs(a,id+1,now+2,ans);
        a[eq[id][0]]+=2;a[eq[id][1]]+=2;a[eq[id][2]]+=2;
    }
}
int main()
{
    for(int i=19;i>=0;i--)
    {
        if(eq[i][0]==eq[i][1])res[i]=res[i+1]+1;
        else res[i]=res[i+1]+2;
    }
    int T;scanf("%d",&T);
    for(int _=1;_<=T;_++)
    {
        for(int i=1;i<=9;i++)scanf("%d",&a[i]);
        int ans=0;
        dfs(a,0,0,ans);
        printf("Case #%d: %d\n",_,ans);
    }
    return 0;
}
/********************

********************/
View Code

F:题意:给一个1到9组成的字符串,按顺序插入+-*/,求最大的数

题解:由于*/优先级高,而且又是被减的,故越小越好,*/插在最后两位即可,注意有6位时,可能有问题,比如,111991,特判掉就好了,前面的+也是,选一个一位数,和剩余的加看哪个大就选哪个

//#pragma comment(linker, "/stack:200000000")
//#pragma GCC optimize("Ofast,no-stack-protector")
//#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
//#pragma GCC optimize("unroll-loops")
#include<bits/stdc++.h>
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define pi acos(-1.0)
#define ll long long
#define vi vector<int>
#define mod 12345678
#define C 0.5772156649
#define ls l,m,rt<<1
#define rs m+1,r,rt<<1|1
#define pil pair<int,ll>
#define pli pair<ll,int>
#define pii pair<int,int>
#define cd complex<double>
#define ull unsigned long long
#define base 1000000000000000000
#define fio ios::sync_with_stdio(false);cin.tie(0)

using namespace std;

const double eps=1e-6;
const int N=300+10,maxn=5000+10,inf=0x3f3f3f3f,INF=0x3f3f3f3f3f3f3f3f;

char s[N];
ll cal(int a,int b)
{
    ll ans=0;
    for(int i=a;i<=b;i++)
        ans=ans*10+(s[i]-'0');
    return ans;
}
int main()
{
    int T;scanf("%d",&T);
    for(int _=1;_<=T;_++)
    {
        printf("Case #%d: ",_);
        scanf("%s",s);
        int n=strlen(s);
        ll ans1=cal(0,0)+cal(1,n-4)-cal(n-3,n-3)*cal(n-2,n-2)/cal(n-1,n-1);
        ll ans2=cal(0,n-5)+cal(n-4,n-4)-cal(n-3,n-3)*cal(n-2,n-2)/cal(n-1,n-1);

        if(n==6){
        long long ans=-1e18;
        for(int i=0;i<n-1;i++)
            for(int j=i+1;j<n-1;j++)
                for(int k=j+1;k<n-1;k++)
                    for(int u=k+1;u<n-1;u++){
                        //printf("%d %d %d %d\n",i,j,k,u);
                        ans1=max(ans1,cal(0,i)+cal(i+1,j)-cal(j+1,k)*cal(k+1,u)/cal(u+1,n-1));
                    }


        }
        printf("%lld\n",max(ans1,ans2));
    }
    return 0;
}
View Code

j:题意:求1到n的每一个数的2的质因子和,

题解:对于每个数x来说可以化成p1^c1*...*pk^ck,对于2^k来说就等价于∑(d|x)|μ(d)|,根据莫比乌斯函数的性质,μ(d)=(-1)^k,d=p1*p2...pk,相当于每次只选k个质因子,然后因为可能为负数,所以变成∑(d|x)μ(d)^2

∑(1<=i<=n)∑(d|i)μ(d)^2,假设j^2是d的最大平方因子,那么∑(k|j)μ(k)=∑(k^2|j^2)μ(k)=∑(k^2|d)μ(k),所以∑(1<=i<=n)∑(d|i)∑(k^2|d)μ(d)=∑(1<=i<=n)μ(k)∑(k^2|d)[n/(k^2)],因为k>sqrt(n)时后面变成了0,所以只需要算前sqrt(n)即可,记忆化后面,μ预处理出来

//#pragma comment(linker, "/stack:200000000")
//#pragma GCC optimize("Ofast,no-stack-protector")
//#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
//#pragma GCC optimize("unroll-loops")
#include<bits/stdc++.h>
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define pi acos(-1.0)
#define ll long long
#define vi vector<int>
#define mod 1000000007
#define C 0.5772156649
#define ls l,m,rt<<1
#define rs m+1,r,rt<<1|1
#define pil pair<int,ll>
#define pli pair<ll,int>
#define pii pair<int,int>
#define cd complex<double>
#define ull unsigned long long
#define base 1000000000000000000
#define fio ios::sync_with_stdio(false);cin.tie(0)

using namespace std;

const double eps=1e-6;
const int N=1000000+10,maxn=5000+10,inf=0x3f3f3f3f,INF=0x3f3f3f3f3f3f3f3f;

ll n,f[N];
int prime[N],mu[N];
bool notprime[N];
void init()
{
    int cnt=0;mu[1]=1;
    for(int i=2;i<N;i++)
    {
        if(!notprime[i])prime[++cnt]=i,mu[i]=-1;
        for(int j=1;j<=cnt&&i*prime[j]<N;j++)
        {
            notprime[i*prime[j]]=1;
            mu[i*prime[j]]=-mu[i];
            if(i%prime[j]==0){mu[i*prime[j]]=0;break;}
        }
    }
}
ll cal(ll n)
{
    if(n<N&&f[n])return f[n];
    ll ans=0;
    for(ll i=1,j;i<=n;i=j+1)
    {
        j=n/(n/i);
        ans+=n/i*(j-i+1)%mod;
        ans%=mod;
    }
    if(n<N)f[n]=ans;
    return ans;
}
int main()
{
    init();
    int T;scanf("%d",&T);
    for(int _=1;_<=T;_++)
    {
        scanf("%lld",&n);
        printf("Case #%d: ",_);
        ll ans=0;
        for(ll i=1;i<=n/i;i++)
        {
            if(mu[i]==0)continue;
            ans+=mu[i]*cal(n/i/i)%mod;
            ans=(ans%mod+mod)%mod;
        }
        printf("%lld\n",ans);
    }
    return 0;
}
/********************

********************/
View Code

K:题意:给你s,n,问你s+1....s+n能不能每个对应一个因子是1到n,而且1到n每个只出现一次

题解:因为如果s+1到s+n和1到n有重叠,那么就选自己,然后剩余的数每个数和因子连边,二分图匹配即可,(也是队友写的)

#include<bits/stdc++.h>
#define LL long long
#define fi first
#define se second
#define mk make_pair
#define pii pair<int,int>
#define piii pair<int,pair<int,int>>

using namespace std;

const int N = 500 + 7;
const int M = 1e4 + 7;
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9 + 7;

int T, n, s, match[N];
bool edge[N][N], vis[N];

bool path(int u) {
    for(int v = 1; v <= n; v++) {
        if(edge[u][v] && !vis[v]) {
            vis[v] = true;
            if(!match[v] || path(match[v])) {
                match[v] = u;
                return true;
            }
        }
    }
    return false;
}

int main() {
    scanf("%d", &T);
    for(int cas = 1; cas <= T; cas++) {
        memset(match, 0, sizeof(match));
        memset(edge, 0, sizeof(edge));
        scanf("%d%d", &n, &s);

        if(s == 0 || s == 1) {
            printf("Case #%d: ", cas);
            puts("Yes");
            continue;
        }

        int l1 = 1, r1 = n;
        int l2 = s + 1, r2 = s + n;
        if(r1 >= l2) {
            swap(l2, r1);
            l2++; r1--;
        }

        n = r2 - l2 + 1;
        if(n > 500) {
            printf("Case #%d: ", cas);
            puts("No");
        } else {
            for(int i = l2; i <= r2; i++) {
                for(int j = l1; j <= r1; j++) {
                    if(i % j == 0) {
                        edge[i - l2 + 1][j - l1 + 1] = true;
                    }
                }
            }
            bool flag = true;
            for(int i = 1; i <= n; i++) {
                    memset(vis, 0, sizeof(vis));
                    if(!path(i)) {
                    flag = false;
                    break;
                }
            }
            printf("Case #%d: ", cas);
            if(flag) puts("Yes");
            else puts("No");
        }
    }
    return 0;
}
/*
*/
View Code

 

posted @ 2018-05-25 15:00  walfy  阅读(263)  评论(0编辑  收藏  举报