trick

priority_queue<int>que//默认最大的先出来 
priority_queue<int,vector<int>,greater<int> >que;///最小的先出来 
struct node{
    int x,y;
    bool operator < (const node &b)const{
        return x<b.x;///大的先出来 
    }
}x1,x2,x3;
y=floor(x)//(向下取整)
y=ceil(x)//(向上取整)

y=round(x)//四舍五入


 排序部分

sort(a,a+n)///快排,不稳定
stable_sort(a,a+n)///归并排序,稳定。有时sort T了 可以用

 定义n*m向量数组

int n,m;
scanf("%d%d",&n,&m);
vector<vector<int> >vv(n,vector<int>(m));

 输出int128

#include <bits/stdc++.h>
using namespace std;
inline __int128 read(){
    __int128 x=0,f=1;
    char ch=getchar();
    while(ch<'0'||ch>'9'){
        if(ch=='-')
            f=-1;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9'){
        x=x*10+ch-'0';
        ch=getchar();
    }
    return x*f;
}

inline void print(__int128 x){
    if(x<0){
        putchar('-');
        x=-x;
    }
    if(x>9)
        print(x/10);
    putchar(x%10+'0');
}

int main(void){
    __int128 a = read();
    __int128 b = read();
    __int128 m =read();
    print((a + b)%m);
    cout<<endl;
    return 0;
}
View Code

 排序写法:

sort(a+1,a+1+n,[&](node A,node B){
        return A.val>B.val;
    });
View Code

 

 取模的组合数:

ll ksm(ll x,ll y,ll p){
    ll res=1ll;
    while(y){
        if(y&1)
            res=res*x%p;
        y>>=1;
        x=x*x%p;
    }
    return res;
}
struct CC{
    static const int N=300010;
    ll fac[N],inv[N];
    CC(){
        fac[0]=1;
        for(int i=1;i<N;i++)
            fac[i]=fac[i-1]*i%mod;
        inv[N-1]=ksm(fac[N-1],mod-2,mod);
        for(int i=N-1;i>=1;i--)
            inv[i-1]=inv[i]*i%mod;
    }
    ll operator()(ll a,ll b){ ///a>=b
        if(a<b || b<0)return 0;
        return fac[a]*inv[a-b]%mod*inv[b]%mod;
    }
    ll A(ll a,ll b){ ///a>=b
        if(a<b || b<0)return 0;
        return fac[a]*inv[a-b]%mod;
    }
}C;
int main(){
    ///直接C(n,m);//n>=m
}
View Code

 求“短”的subsequence(非连续,不重复)在原串出现次数(含问号,全能字符),复杂度:O(nm)(https://codeforces.com/contest/1426/problem/F

#include<bits/stdc++.h>
using namespace std;
#define pb push_back
#define MP make_pair
#define lson root<<1,l,midd
#define rson root<<1|1,midd+1,r
typedef long long ll;
const int mod=1e9+7;
const int M=2e6+6;
const int inf=0x3f3f3f3f;
const ll INF=1e18;
char s[M];
ll f[10];
int main(){
    int n;
    scanf("%d%s",&n,s+1);
    f[0]=1ll;
    f[1]=f[2]=f[3]=0;
    for(int i = 1; i <= n; i++){

        if(s[i]=='?'){
            f[3]=(f[3]*3ll+f[2])%mod;
            f[2]=(f[2]*3ll+f[1])%mod;
            f[1]=(f[1]*3ll+f[0])%mod;
            f[0]=(f[0]*3ll)%mod;



        }
        else f[s[i]-'a'+1] = (f[s[i]-'a'+1]+f[s[i]-'a'])%mod;

    }
    printf("%lld\n",f[3]);
    return 0;
}

/***********************求“2020”的子序列的个数***************/
/***********************二分***************/



const int N=1e5+5;

    int i,j,k;
    int n,m,t;
    int a[N];

int C(int aim)
{
    int bits[5]={0};
    bits[1]=aim;
    for(int i=1;i<=n;i++){
        if(a[i]==1) continue;
        if(a[i]==2) {
            if(bits[1]) bits[1]--,bits[2]++;
            else if(bits[3]) bits[3]--,bits[4]++;
        }
        if(a[i]==0){
            if(bits[2]) bits[2]--,bits[3]++;
            else if(bits[4]) bits[4]--;
        }
    }
    if(bits[1] || bits[2] || bits[3] || bits[4]) return 0;
    return 1;
}

int main()
{
    //IOS;
    while(~sd(n)){
        for(int i=1;i<=n;i++) scanf("%1d",&a[i]);
        int l=0,r=n/4+1,ans=0;
        while(r>=l){
            int mid=l+r>>1;
            if(C(mid)) l=mid+1,ans=mid;
            else r=mid-1;
        }
        pd(ans);
    }
    //PAUSE;
    return 0;
}
View Code

 

 求1~n的前缀和的前缀和:

        ans = n * n * (n + 1) / 2;///把每一个前缀和看作到n的前缀和,总共有n个;
 
        ans -= n * (n + 1) * (2 * n + 1) / 6;///列出来发现可以把上一项减去1^2+2^2+3^2+4^2……n^2=n * (n + 1) * (2 * n + 1) / 6 再加上1~n的前缀和
 
        ans += n * (n + 1) / 2;
View Code

 set去最后一个值,定义时依照制定的来排序:

///依照dfs序来排序
struct cmp{
    bool operator() (const int &x,const int &y)const{
        return dfn[x]<dfn[y];
    }
};
set<int,cmp>st[M];
///
cout<<ser.rbegin()<<endl;
View Code

 vector 去重:

    sort(vec.begin(), vec.end());
    vec.erase(unique(vec.begin(), vec.end()), vec.end());
for(int x : vec)
        cout << x << ",";
View Code

 构建SAM:

https://yutong.site/sam/

 

问(长度为n)每个a数组中长度为k的子数组的最小值((n-k+1)个)形成的数组是否为一个排列

#include<bits/stdc++.h>
using namespace std;
#define pb push_back
#define MP make_pair
#define UM unordered_map
typedef long long ll;
const int mod=1e9+7;
const int inf=0x3f3f3f3f;
const ll INF=1e18;
#define pi 3.1415926535898
#define DEC (pi/180)
const int M=1e6+5;
bool ans[M];
int a[M],cnt[M];
void py(){
    puts("Yes");
}
void pn(){
    puts("No");
}
int main(){
    int T;
    scanf("%d",&T);
    while(T--){
        int n;
        scanf("%d",&n);
        for(int i=1;i<=n;i++) cnt[i]=0,ans[i]=false;
        for(int i=1;i<=n;i++){
            scanf("%d",&a[i]);
            cnt[a[i]]++;
        }
        int tot=1;
        for(int i=1;i<=n;tot++,i++){
            if(!cnt[i])
                break;
        }
        ans[1] = (tot==n+1 ? true : false);
        ans[n] = (cnt[1]>0 ? true : false);
        int l=1,r=n;
        for(int i=n;i>=1;i--){
            int now=n-i+1;
            if(!cnt[now])
                break;
            ans[i]=true;
            if(--cnt[now]==0&&(a[l]==now||a[r]==now)&&cnt[now+1]){
                cnt[now]--;
                if(a[l]==now) l++;
                if(a[r]==now) r--;
                continue;
            }
            break;
        }
        for(int i=1;i<=n;i++)printf("%d",ans[i]);
        puts("");
    }
    return 0;
}
View Code

乘积的最短路,一般要转为对数log,变相地变成加的形式

 

关于auto :dfs函数和返回函数写法不一样:

/********dfs***********/
function<void(int)> dfs = [&](int u){
            vis[u]=1;
            a.pb(u);
            for(auto v:g[u]){
                if(!vis[v])
                    dfs(v);
            }
        };
/******不用调用自己的函数******/
auto Union = [&] (int x, int y) {
        x = find(x), y = find(y);
        if (x != y) {
            f[x] = y;
            return true;
        }
        return false;
    };
View Code

 求b数组的每一项和a数组的n个数相加组成的n个数的gcd

考虑 gcd 的另一种计算方式,gcd(a1,a2,…,an)=gcd(a1,a2−a1,a3−a2,…,an−an−1),

那么就有 gcd(a1+x,a2+x,…,an+x)=gcd(a1+x,a2−a1,a3−a2,…,an−an−1),

预处理出 G=gcd(a2−a1,a3−a2,…,an−an−1),然后对于每组询问,输出 gcd(G,a1+bj) 即可。

#include<bits/stdc++.h>
using namespace std;
#define pb push_back
#define MP make_pair
#define UM unordered_map
typedef long long ll;
const int mod=1e9+7;
const int inf=0x3f3f3f3f;
const ll INF=1e18;
#define pi 3.1415926535898
#define DEC (pi/180)
const int M=3e5+5;
ll a[M];
void pn(){
    puts("NO");
}
void py(){
    puts("YES");
}
int main(){
 
    int n,m;
    cin>>n>>m;
    ll g=0,g2=0;
    for(int i=1;i<=n;i++){
        cin>>a[i];
 
    }
    sort(a+1,a+1+n);
    for(int i=1;i<=n;i++){
        if(i>=2){
            g2=__gcd(g2,a[i]-a[i-1]);
        }
    }
    for(int i=1;i<=m;i++){
        ll x;
        cin>>x;
 
            cout<<__gcd(a[1]+x,g2)<<endl;
 
    }
    return 0;
}
View Code

 根据年月日判断星期

//基姆拉尔森计算公式根据日期判断星期几
void CalculateWeekDay(int y, int m,int d){
    if(m==1||m==2) m+=12,y--;
    int iWeek = (d+2*m+3*(m+1)/5+y+y/4-y/100+y/400)%7;
    switch(iWeek){
        case 0: printf("星期一\n"); break;
         case 1: printf("星期二\n"); break;
         case 2: printf("星期三\n"); break;
         case 3: printf("星期四\n"); break;
         case 4: printf("星期五\n"); break;
         case 5: printf("星期六\n"); break;
         case 6: printf("星期日\n"); break;
    }
}
int main()
{
    CalculateWeekDay(2015,9,17);
    return 0;
}
View Code

 找ax+ay==aw+aq 范围n<=2e5. ai<=2e6(n*(n-1)/2种不同的sum 的可能 的 序列,而 组合最多时2*2e6,也就是n*(n-1)/2<=2*2e6,得到的n就很小了)

#include<bits/stdc++.h>
using namespace std;
const int M=998244353;
const int N=5000005,E=524288;
int n,a[N],i,j;
struct str{
    int x,y;
};
vector<str> vis[N];
int main()
{
#ifndef ONLINE_JUDGE
    freopen("a.in","r",stdin);
    freopen("a.out","w",stdout);
#endif
    scanf("%d",&n);
    for(i=1;i<=n;++i)
        scanf("%d",&a[i]);
    for(i=1;i<=n;++i)
        for(j=1;j<=n-i;++j)
        {
            for(auto it:vis[a[j]+a[i+j]])
                if(it.x!=j&&it.y!=i+j&&it.y!=j&&it.x!=i+j)
                {
                    puts("YES");
                    printf("%d %d %d %d",it.x,it.y,j,i+j);
                    return 0;
                }
            vis[a[j]+a[i+j]].push_back({j,i+j});
        }
    puts("NO");
}
View Code

 找字典序最小的子序列并且是一个排列

https://ac.nowcoder.com/acm/contest/12606/E

#include<bits/stdc++.h>
using namespace std;
const int M=2e5+5;
int vis[M],a[M],las[M],ans[M];
int main(){
    int n,k;
    scanf("%d%d",&n,&k);
    for(int i=1;i<=n;i++)
        scanf("%d",&a[i]),las[a[i]]=i;
    int tot=0;
    for(int i=1;i<=n;i++){
        if(vis[a[i]])continue;
        while(tot>=1&&ans[tot]>=a[i]&&las[ans[tot]]>=i)
            vis[ans[tot--]]=0;
        vis[a[i]]=1;
        ans[++tot]=a[i];
    }
    for(int i=1;i<=tot;i++)
        printf("%d ",ans[i]);
    return 0;
}
View Code

 小圈序列n和大圈序列m无限循环,求pos1(在n中)和pos2(在m中)的最小相遇位置(crt扩展中国剩余定理)crt数组

练习:给定n个数的序列(各不相同) 和m个数的序列(各不相同),俩个都是无限循环的序列,问前缀恰好有k个不相同的个数 的位置是哪一个位置(n,m<=5e5,k<=1e12)

https://codeforces.com/contest/1501/problem/D

#include <bits/stdc++.h>

using namespace std;

#define pb emplace_back
#define MP make_pair
#define pii pair<int,int>
#define pll pair<ll,ll>
#define lson rt<<1
#define rson rt<<1|1
typedef long long ll;
typedef double db;
const int INF = 0x3f3f3f3f;
const db eps = 1e-6;
const int MAXN = 5e5 + 7;
ll n,m,k;
int p1[MAXN<<1],p2[MAXN<<1];//2 * max(n,m) 一个序列里面的数都不同保证了每一个数位置的唯一性
//二分 + crt
/************exCRT*************/
ll gcd(ll a,ll b) {
    return b == 0 ? a : gcd(b,a%b);
}
ll exgcd(ll a,ll b,ll &x,ll &y) {
    if(b == 0) {
        x = 1,y = 0;
        return a;
    }
    else {
        ll res = exgcd(b,a%b,x,y);
        ll t = x;
        x = y;
        y = t - a / b * y;
        return res;
    }
}
ll excrt(ll m1,ll m2,ll a1,ll a2) {//解决模数不互质的情况
    ll x,y,c,g;
    c = a2 - a1;
    g = exgcd(m1,m2,x,y);
    x = x * c / g;//把方程右侧化为
    y = m2 / g;
    x = (x % y + y) % y;//求最小正整数解
    a1 = a1 + x * m1;
    m1 = m1 * m2 / g;
    return a1;//解x
}
/****************************/
ll crt[MAXN<<1],LCM;

bool check(ll x) {
    ll sum = 0,ma = 2 * max(n,m);
    for(int i = 1;i <= ma;i ++) {
        if(!p1[i] || !p2[i]) continue;
        if(!crt[i] || x < crt[i]) continue;//别越界
        //x通解 x = x0 + lcm(m1,m2);
        sum += (x - crt[i]) / LCM + 1;//看看后面还有几个通解
        if(x - sum < k) return false;
    }
    return x - sum >= k;//总为x天,其中sum天相同,则x - sum天不同
}

int main() {
    scanf("%lld%lld%lld",&n,&m,&k);
    for(int i = 1,x;i <= n;i ++) {
        scanf("%d",&x);
        p1[x] = i;
    }
    for(int i = 1,x;i <= m;i ++) {
        scanf("%d",&x);
        p2[x] = i;
    }
    ll ma = 2 * max(n,m),g = gcd(n,m);
    for(int i = 1;i <= ma;i ++) {//求解每一个值的最小出现的位置在哪
        if(!p1[i] || !p2[i]) continue;
        if(abs(p1[i]-p2[i]) % g != 0) continue;
        crt[i] = excrt(n,m,p1[i],p2[i]);//存的是相等的值出现的位置
    }
    LCM = n * m / g;
    ll l = 1,r = ma * k,ans;//ma * k就是相等比较多的极端情况
    while(l <= r) {
        ll mid = (l + r) >> 1;
        if(check(mid)) {
            ans =  mid;
            r = mid - 1;
        }
        else l = mid + 1;
    }
    printf("%lld\n",ans);
    return 0;
}
View Code

从左上角到右下角有障碍(列数行数算组合数,障碍物容斥)

https://codeforces.com/problemset/problem/559/C

#include<bits/stdc++.h>
using namespace std;
#define pb push_back
#define MP make_pair
#define UM unordered_map
#define pii pair<int,int>
#define lson root<<1,l,midd
#define rson root<<1|1,midd+1,r
#define lc root<<1
#define rc root<<1|1
typedef long long ll;
const int mod=1e9+7;
const int inf=0x3f3f3f3f;
const ll INF=1e18;
const int N=2002;
const int M=2e5+5;
#define pi 3.1415926535898
#define DEC (pi/180)
struct node{
    int x,y;
}a[N];
ll fac[M],inv[M],f[M];
ll ksm(ll x,ll y){
    ll t=1;
    while(y){
        if(y&1)
            t=t*x%mod;
        y>>=1;
        x=x*x%mod;
    }
    return t;
}
void init(int n){
    fac[0]=inv[0]=1;
    for(int i=1;i<=n;i++){

        fac[i]=(fac[i-1]*i)%mod;
        inv[i]=ksm(fac[i],mod-2);
    }
}
ll C(int n,int m){
    if(n<0||m<0) return 0;
    return fac[n]*inv[n-m]%mod*inv[m]%mod;
}
int main(){
    int h,w,k;
    scanf("%d%d%d",&h,&w,&k);
    for(int i=0;i<k;i++)
        scanf("%d%d",&a[i].x,&a[i].y);
    init(h+w);

    a[k].x=h, a[k].y=w;

    sort(a,a+k+1,[&](node A,node B){
        if(A.x==B.x) return A.y<B.y;
        return A.x<B.x;
    });

    for(int i=0;i<=k;i++){
        f[i]=C(a[i].x-1+a[i].y-1,a[i].x-1);///(C(n+m,n))
        ///减去已经算过的
        for(int j=0;j<i;j++){
            int n=a[i].x-a[j].x;
            int m=a[i].y-a[j].y;
            if(n>=0&&m>=0)
                f[i]=(f[i]-f[j]*C(n+m,n)%mod+mod)%mod;
        }
    }
    printf("%lld\n",f[k]);
    return 0;
}
View Code

 在mian中写函数auto

auto matches = [&](int i, int j) {
            if (i == 0) {
                return false;
            }
            if (p[j - 1] == '.') {
                return true;
            }
            return s[i - 1] == p[j - 1];
        };
View Code

 马拉车

class Solution {
public:
    int getLongestPalindrome(string A, int n) {
        // write code here
        string B = "";
        
        if(n==0)
            B="^$";
        else{
            B = '^';
            for(int i = 0; i < n; i++){
                B += '#';
                B += A[i];
            }
            B += "#$";
        }
        int len = B.size();
        vector<int>P(len,0);
        int C = 0, R = 0;
        for(int i = 1; i < len-1; i++){
            int posi = 2 * C - i;
            if(R>i){
                P[i] = min(R - i,P[posi]);
            }
            else{
                P[i] = 0;
            }
            while(B[i - 1 - P[i]] == B[i + 1 + P[i]])
                P[i]++;
            if(i + P[i] > R){
                R = i + P[i];
                C = i;
            }
        }
        int maxlen = 0, nowid = 0;
        for(int i = 1; i < len - 1; i++){
            if(P[i] > maxlen){
                maxlen = P[i];
                nowid=i;
            }
        }
        ///cout<<A.substr((nowid-maxlen)/2,maxlen)<<endl;
        return maxlen;
    }
};
View Code

 单调栈

///[L[i],i]位置上的值都大于a[i]
        ///[i,R[i]]位置上的值都大于a[i]
        for(int i=1;i<=n;i++)
        l[i]=r[i]=i;
        for(int i=1;i<=n;i++)
        {
            while(l[i]-1>=1&&h[i]<=h[l[i]-1])
            l[i]=l[l[i]-1];
        }
        for(int i=n;i>=1;i--)
        {
            while(r[i]+1<=n&&h[i]<=h[r[i]+1])
            r[i]=r[r[i]+1];
        }
View Code

 

posted @ 2019-09-02 23:18  starve_to_death  阅读(198)  评论(0编辑  收藏  举报