Codeforces #174 Div2

Cows and Primitive Roots

  原根,目前只有暴力求解,看了百度百科才知道。因为 x < p,  且 p <= 2000

View Code
#include<stdio.h>
#include<stdlib.h>


int p;

int pow( int x, int n ){
    int res = 1;
    while( n ){
        if( n&1 ) res = (res*x)%p;
        x = x*x%p;
        n >>= 1; 
    }
    return res;
}

bool legal( int x ){
    if( pow( x, p-1 ) - 1 ) return false;
    else{
        for(int i = 1; i < p-1; i++ )
            if( (pow(x,i)-1) == 0 ) return false;
        return true;
    }
}
int main(){
    while( scanf("%d", &p) != EOF)
    {
        int res = 0;
        for(int x = 1; x < p; x++ )
        {
            if( legal( x ) )
                res++;
        }
        printf("%d\n", res );    
    }
    return 0;
}

Cows and Poker Game

  题目描述的,最后一句话感觉有点坑,若其他人为 F或 A, 自己是A或I 才可以举手,只需要统计I数量,

然后分析即可。

View Code
#include<stdio.h>
#include<string.h>


const int N = 200007;
char str[N];

int main(){
    int n;
    while( scanf("%d", &n) != EOF )
    {
        scanf("%s", str );
        int len = strlen(str);
        int cnt_A = 0, cnt_I = 0;    
        for(int i = 0; i < len; i++)
            if( str[i] == 'I' ) cnt_I++;
            else if( str[i] == 'A' ) cnt_A++;    
        if( cnt_I == 1 ) printf("1\n");
        else if( cnt_I == 0 ) printf("%d\n", cnt_A);
        else    printf("0\n");
    }
    return 0;
}

Cows and Sequence

  区间更新,单点更新,区间求和,可以用线段树来维护,时间复杂度为 Nlog(N) ,

不过要注意原本里头有1个元素了,极限再添加 N个, 则最大有 N+1 个节点

  解法2,主要还是区间更新然后删除最后一个节点时候的处理,其实可以借鉴线段树区间更新,

中的 push_down 操作,借助辅助数组来实现,代码可以很精简。

解法一代码

View Code
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<algorithm>
using namespace std;

#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
typedef long long LL;

const int N = 200010;

LL sum[N<<2], add[N<<2];
void push_up( int rt ){
    sum[rt] = sum[rt<<1] + sum[rt<<1|1];
}
void push_down( int rt, int m){
    if( add[rt] ){
        add[rt<<1] += add[rt];
        add[rt<<1|1] += add[rt];    
        sum[rt<<1] += (LL)(m-(m>>1))*add[rt];
        sum[rt<<1|1] += (LL)(m>>1)*add[rt];
        add[rt] = 0;
    }
}

void build( int l, int r, int rt ){
    add[rt] = sum[rt] = 0;
    if( l == r ) return;
    int m = (l+r)>>1;
    build( lson );
    build( rson );
    //push_up( rt );
}
void update( int L, int R, LL c, int l, int r,int rt ){
    if( (L<=l) && (r<=R) ){
        add[rt] += c;
        sum[rt] += (LL)c*(r-l+1);
        return;    
    }
    push_down( rt, r-l+1 );
    int m = (l+r)>>1;
    if( L <= m ) update( L, R, c, lson );
    if( m < R ) update( L, R, c, rson );
    push_up( rt );
}
LL query( int L, int R, int l, int r, int rt ){
    if( (L<=l) && (r<=R) )
        return sum[rt];
    push_down( rt, r-l+1 );
    int m = (l+r)>>1;
    LL ret = 0;
    if( L <= m ) ret += query( L, R, lson );
    if( m < R )  ret += query( L, R, rson );
    return ret;
}

int main(){
//    freopen("1.in", "r", stdin);
//    freopen("test.out","w",stdout);

    int T, n = 1, maxn = 200001;
    build( 1, maxn, 1 );    

    scanf("%d", &T);
    for(int i = 0; i < T; i++){
        int op, a, b;
        scanf("%d", &op);
        if( op == 1 ){
            scanf("%d%d", &a, &b );
            update( 1,a, b,  1,maxn,1 ); 
        }
        else if( op == 2 ){
            scanf("%d", &a );
            n++;
            update( n,n,a, 1,maxn, 1 );        
        }
        else{
            if( n > 1 ) {
                LL tmp = query( n,n, 1,maxn,1 );    
                update( n,n, -tmp, 1,maxn, 1 );
                --n;    
            }    
        }
    
        LL res = query( 1, maxn, 1, maxn, 1 );
//        printf("%lld\n", res );
                printf("%.9lf\n", res*1./n );
    }    
    return 0;
}

解法二代码

View Code
#include<stdio.h>
#include<string.h>
#include<stdlib.h>

typedef long long LL;

const int N = 2e5+10;
LL s, a[N], c[N];

int main(){
    int n = 1, m;
    scanf("%d", &m);
    while( m-- ){
        int op, x, y;
        scanf("%d", &op);
        if( op == 1 ){
            scanf("%d%d", &x,&y);    
            s += (1LL)*x*y; c[x] += y;
        }
        else if( op == 2 ){
            scanf("%d", &y);
            s += y; a[++n] = y;
        }
        else{
            s -= a[n]; a[n] = 0;
            c[n-1] += c[n]; 
            s -= c[n]; c[n] = 0;
            --n;
        }    
        printf("%.9lf\n", s*1./n);    
    }
    return 0;
}

Cow Program

  因为 A【1】 每次都在变换,但是操作对于x而言只有 +a[x] ,与 -a[x],

若其第二次回到 1 位置,若为 +a[x], 则陷入死循环,若为 -a[x],则必定 1-a[1] 终断,

所以我们可以得出结论,a[1] = i ,的值虽然变换,但不对后面的产生影响,所以可以使用

记忆化搜索或者DP来解。

View Code
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<algorithm>
using namespace std;

typedef long long LL;

const int N = 2e5+10;

LL dp[2][N];
int n, a[N];
int vis[2][N];

LL dfs( int i, int cur, int x ){
    if( x <= 0 || x > n ) return 0;
    // 循环,继续走下去回陷入循环 
    if( (vis[cur][x] == i) || (vis[cur][x] == -1 ) ) return -1;

    if( vis[cur][x] ) return dp[cur][x];
    vis[cur][x] = i;    
    
    LL tmp = dfs( i, !cur, x + (cur?(-a[x]):a[x]) );

    if( tmp == -1 ) return (vis[cur][x] = -1);
    else    return dp[cur][x]= tmp+a[x];

}
int main(){
    scanf("%d", &n );
    for(int i = 2; i <= n; i++)
        scanf("%d", &a[i] );
    for(int i = 1; i <= n-1; i++)
    {
        vis[0][1]=0,a[1] = i;
        LL y = dfs(i, 0, 1);
        printf("%lld\n", y );    
    }
    return 0;
}

Coin Troubles

  还没有写,A了后再来补充~~~

原文地址:https://www.cnblogs.com/yefeng1627/p/2968974.html