• cf Round 603


    A.Alternative Thinking(思维)

    给出一个01串,你可以取反其中一个连续子串,问取反后的01子串的最长非连续010101串的长度是多少。

    我们随便翻一个连续子串,显然翻完之后,对于这个连续子串而言,最后的答案一定不会变优。
    只会对你翻的左端点和右端点相邻的数字产生贡献。我们计左端点为l,右端点为r。
    而且要想最大化贡献,必须要使得这个a[l]和a[l-1]一样。a[r]和a[r+1]一样。
    那么我们只要找到可以使这个贡献获得最大时的条件就行了。

    # include <cstdio>
    # include <cstring>
    # include <cstdlib>
    # include <iostream>
    # include <vector>
    # include <queue>
    # include <stack>
    # include <map>
    # include <set>
    # include <cmath>
    # include <algorithm>
    using namespace std;
    # define lowbit(x) ((x)&(-x))
    # define pi acos(-1.0)
    # define eps 1e-3
    # define MOD 1000000007
    # define INF 1000000000
    # define mem(a,b) memset(a,b,sizeof(a))
    # define FOR(i,a,n) for(int i=a; i<=n; ++i)
    # define FO(i,a,n) for(int i=a; i<n; ++i)
    # define bug puts("H");
    # define lch p<<1,l,mid
    # define rch p<<1|1,mid+1,r
    # define mp make_pair
    # define pb push_back
    # define fi first
    # define se second
    typedef pair<int,int> PII;
    typedef vector<int> VI;
    # pragma comment(linker, "/STACK:1024000000,1024000000")
    typedef long long LL;
    typedef unsigned long long ULL;
    int _MAX(int a, int b){return a>b?a:b;}
    int _MIN(int a, int b){return a>b?b:a;}
    int Scan() {
        int res=0, flag=0;
        char ch;
        if((ch=getchar())=='-') flag=1;
        else if(ch>='0'&&ch<='9') res=ch-'0';
        while((ch=getchar())>='0'&&ch<='9')  res=res*10+(ch-'0');
        return flag?-res:res;
    }
    void Out(int a) {
        if(a<0) {putchar('-'); a=-a;}
        if(a>=10) Out(a/10);
        putchar(a%10+'0');
    }
    const int N=100005;
    char s[N];
    
    int main ()
    {
        int n, cnt=0, ans1=0, ans2=0;
        char f=' ';
        scanf("%d%s",&n,s+1);
        FOR(i,1,n) {
            if (s[i]=='1') ans2=ans1+1;
            else ans1=ans2+1;
            if (f==s[i]) cnt++;
            f=s[i];
        }
        int ans=max(ans1,ans2);
        if (cnt==1) ans+=1;
        else if (cnt>=2) ans+=2;
        printf("%d
    ",ans);
        return 0;
    }
    View Code

    B.Moodular Arithmetic(数论)

    告诉你p和k,其中(0<=k<=p-1),x属于{0,1,2,3,....,p-1},f函数要满足f(k*x%p)=k*f(x)%p,f(x)的范围必须在[0,p-1]内,问这样的f函数有多少个

    先观察小情形。
    k=0时,此时有f(0)=0.即除了0其他可以随便乱取。那么我们得到ans=p^(p-1).
    k=1时,此时有f(x)=f(x).此时随便乱取。那么我们得到ans=p^p.
    后面我们发现就不好办了。
    但是我们发现f(k*k*x)=k*f(k*x)%p=k*(k*f(x)%p)%p.
    这不是乘法取模吗。那么则有f(k^n*x%p)=(k^n)%p*f(x)%p.
    我们要是能使k^n%p=1就好了,那么就会有n个数在一个环上面。我们令n最小。
    那么n就是k关于p的一个阶。
    因为f(0)=0,那么答案就是p^((p-1)/n).

    # include <cstdio>
    # include <cstring>
    # include <cstdlib>
    # include <iostream>
    # include <vector>
    # include <queue>
    # include <stack>
    # include <map>
    # include <set>
    # include <cmath>
    # include <algorithm>
    using namespace std;
    # define lowbit(x) ((x)&(-x))
    # define pi acos(-1.0)
    # define eps 1e-3
    # define MOD 1000000007
    # define INF 1000000000
    # define mem(a,b) memset(a,b,sizeof(a))
    # define FOR(i,a,n) for(int i=a; i<=n; ++i)
    # define FO(i,a,n) for(int i=a; i<n; ++i)
    # define bug puts("H");
    # define lch p<<1,l,mid
    # define rch p<<1|1,mid+1,r
    # define mp make_pair
    # define pb push_back
    # define fi first
    # define se second
    typedef pair<int,int> PII;
    typedef vector<int> VI;
    # pragma comment(linker, "/STACK:1024000000,1024000000")
    typedef long long LL;
    typedef unsigned long long ULL;
    int _MAX(int a, int b){return a>b?a:b;}
    int _MIN(int a, int b){return a>b?b:a;}
    int Scan() {
        int res=0, flag=0;
        char ch;
        if((ch=getchar())=='-') flag=1;
        else if(ch>='0'&&ch<='9') res=ch-'0';
        while((ch=getchar())>='0'&&ch<='9')  res=res*10+(ch-'0');
        return flag?-res:res;
    }
    void Out(int a) {
        if(a<0) {putchar('-'); a=-a;}
        if(a>=10) Out(a/10);
        putchar(a%10+'0');
    }
    const int N=100005;
    
    LL muti_mod(LL a,LL b,LL c)
    {
        a%=c; b%=c;
        LL ret=0;
        while (b) {
            if (b&1){ret+=a; if (ret>=c) ret-=c;}
            a<<=1;
            if (a>=c) a-=c;
            b>>=1;
        }
        return ret;
    }
    LL pow_mod(LL x,LL n,LL mod)
    {
        if (n==1) return x%mod;
        int bit[64], k=0;
        while (n) bit[k++]=n&1, n>>=1;
        LL ret=1;
        for (k=k-1; k>=0; --k){
            ret=muti_mod(ret,ret,mod);
            if (bit[k]==1) ret=muti_mod(ret,x,mod);
        }
        return ret;
    }
    int eul(LL p, LL k)
    {
        FO(i,2,p) if ((p-1)%i==0&&pow_mod(k,(LL)i,p)==1) return i;
    }
    int main ()
    {
        LL p, k;
        scanf("%lld%lld",&p,&k);
        if (k==0) printf("%lld
    ",pow_mod(p,p-1,MOD));
        else if (k==1) printf("%lld
    ",pow_mod(p,p,MOD));
        else {
            int temp=eul(p,k);
            printf("%lld
    ",pow_mod(p,(p-1)/temp,MOD));
        }
        return 0;
    }
    View Code

    C.Lieges of Legendre(SG函数)

    变形版nim游戏,操作有两个,1.取出一个石子。2.把一堆偶数个石子变成k堆偶数/2个石子。

    分析:
    抽象成DAG,这个DAG的顶点度数最大为2,打sg表找规律。
    发现k为偶数时很简单。 k为奇数时。模拟求sg函数,可以递归的求出sg。
    复杂度O(n*logai).

    # include <cstdio>
    # include <cstring>
    # include <cstdlib>
    # include <iostream>
    # include <vector>
    # include <queue>
    # include <stack>
    # include <map>
    # include <set>
    # include <cmath>
    # include <algorithm>
    using namespace std;
    # define lowbit(x) ((x)&(-x))
    # define pi acos(-1.0)
    # define eps 1e-3
    # define MOD 1000000007
    # define INF 1000000000
    # define mem(a,b) memset(a,b,sizeof(a))
    # define FOR(i,a,n) for(int i=a; i<=n; ++i)
    # define FO(i,a,n) for(int i=a; i<n; ++i)
    # define bug puts("H");
    # define lch p<<1,l,mid
    # define rch p<<1|1,mid+1,r
    # define mp make_pair
    # define pb push_back
    # define fi first
    # define se second
    typedef pair<int,int> PII;
    typedef vector<int> VI;
    # pragma comment(linker, "/STACK:1024000000,1024000000")
    typedef long long LL;
    typedef unsigned long long ULL;
    int _MAX(int a, int b){return a>b?a:b;}
    int _MIN(int a, int b){return a>b?b:a;}
    int Scan() {
        int res=0, flag=0;
        char ch;
        if((ch=getchar())=='-') flag=1;
        else if(ch>='0'&&ch<='9') res=ch-'0';
        while((ch=getchar())>='0'&&ch<='9')  res=res*10+(ch-'0');
        return flag?-res:res;
    }
    void Out(int a) {
        if(a<0) {putchar('-'); a=-a;}
        if(a>=10) Out(a/10);
        putchar(a%10+'0');
    }
    const int N=100005;
    
    int n, k, a[7]={0,1,0,1,2,0,2};
    
    int find(int x)
    {
        if (k%2==0) {
            if (x<=2) return x;
            else return x%2==0;
        }
        else {
            if (x<=6) return a[x];
            if (x&1) return 0;
            else {
                if (find(x/2)==1) return 2;
                else return 1;
            }
        }
    }
    int main ()
    {
        int temp, ans=0;
        scanf("%d%d",&n,&k);
        while (n--) scanf("%d",&temp), ans^=find(temp);
        puts(ans?"Kevin":"Nicky");
    }
    View Code

    D.Ruminations on Ruminants(数学)

    枚举出三个点之后判定是否过原点还是可以的.但是不能枚举.
    只知道相加180这个限制是不好想办法的.
    所以转化成:远点向直线做垂线,只有三个垂足在同一条直线上的时候,才行.
    那么我们先做找出来垂足,然后数三个点在一条直线的三元组个数.
    转化一下,就是两点确定一条直线,然后再看每一条直线上有多少个点,用组合数算.
    但是这样不好写(还要转成直线的方程),i j k(i < j < k), 我们枚举i,要求j和k相对于i的斜率必须一样. 如果有重合的点,那么任意一个第三个点都可以.
    注意,要全部用整数,先联立方程算出来垂足,用分子分母表示,然后求斜率减之后也化成标准的形式.

    #include <iostream>
    #include <cstdio>
    #include <cmath>
    #include <cstring>
    #include <map>
    
    using namespace std;
    
    typedef long long ll;
    
    const int maxn = 2000 + 100;
    int n, a[maxn], b[maxn], c[maxn], ac[maxn], bc[maxn], a2b2[maxn];
    ll res;
    struct Point {
        ll x, y;
    };
    
    ll gcd(ll x, ll y) {
        if(y == 0)
        return x;
        return gcd(y, x % y);
    }
    Point getStand(Point t) {
        if(t.x == 0) {
        if(t.y == 0)
            return t;
        t.y = 1;
        return t;
        }
        else if(t.y == 0) {
        t.x = 1;
        return t;
        }
        ll d = gcd(abs(t.x), abs(t.y));
        t.x /= d;
        t.y /= d;
        if(t.x < 0 && t.y < 0 || t.x > 0 && t.y < 0) {
        t.x = -t.x;
        t.y = -t.y;
        }
        return t;
    }
    void solve() {
        for(int i = 1; i <= n; i++) {
        ac[i] = a[i] * c[i];
        bc[i] = b[i] * c[i];
        a2b2[i] = a[i] * a[i] + b[i] * b[i];
        }
        res = 0;
        for(int i = 1; i <= n; i++) {
        map<ll, map<ll, ll> > mp;
        int same = 0, ans = 0;
        for(int j = i + 1; j <= n; j++) {
            Point t;
            t.x = (ll)a2b2[j] * (ll)ac[i] - (ll)a2b2[i] * (ll)ac[j];
            t.y = (ll)a2b2[j] * (ll)bc[i] - (ll)a2b2[i] * (ll)bc[j];
            t = getStand(t);
            if(t.x == 0 && t.y == 0) {
            same++;
            ans += (j - i - 1);
            }
            else {
            ans += mp[t.x][t.y] + same;
            mp[t.x][t.y]++;
            }
        }
        res += ans;
        }
        printf("%I64d
    ", res);
    }
    
    int main() {
      //  freopen("D.txt", "r", stdin);
        while(scanf("%d", &n) != EOF) {
        for(int i = 1; i <= n; i++) {
            scanf("%d%d%d", &a[i], &b[i], &c[i]);
        }
        solve();
        }
        return 0;
    }
    View Code

    E.Pastoral Oddities(待填坑)

  • 相关阅读:
    理解SynchronizationContext,如何在Winform里面跨线程访问UI控件
    ThreadPool.QueueUserWorkItem引发的血案,线程池异步非正确姿势导致程序闪退的问题
    实战经验分享之C#对象XML序列化
    C#wxpay和alipay
    C#调用windows api 实现打印机控制
    C#winform程序关闭计算机的正确姿势
    自动化控制之线程池的使用
    自动化控制之重码校验
    (转)C#中的那些全局异常捕获
    android studio 2.32躺坑记
  • 原文地址:https://www.cnblogs.com/lishiyao/p/6259668.html
Copyright © 2020-2023  润新知