• 19-11-09-∵


    先挖个坑,不然多半会忘掉

    关于对拍?

    大家都是怎么写的呀?

    $ ext{vim}$玄手又来发广告了。

    写下面这个,不用再看一眼对拍:

    if(system("diff a.out b.out -b -B -q")){
    	puts("WA");
    	system("gnome-terminal --command="vimdiff a.out b.out"");
    	system("gnome-terminal --command="vim 1.in"");
    	return 0;
    }
    

    只要$ ext{wa}$了就突然钻出一个光头弹出两个窗口,就是用$ ext{vim}$打开那三个东西,$ ext{gedit}$玩家请自行修改。

    总结:

    T1一看是个$Theta(N^2)$题。

    emm。于是先码一个暴力,然后接着一个贪心。

    疯狂对拍$color{forestgreen}{ ext{AC}}$

    T2不是很清楚怎么做,然后先写暴力。

    T3……写了一个特判,然后就是一大堆测试点分治(可以这很NOIPCSP-S)

    状态还行。

    27
    Miemeng 100
    00:00:33
    40
    00:00:34
    55
    00:00:34
    195
    00:00:34

    TJ解:

    T1:

    我的考试方法仿佛伪了……

    我当时是枚举中间点直接暴力向左右扫并将相同的合并过来,

    所以因为是直接判的长度而不是长度加前缀和,于是有时候不对。

    但是因为枚举了不同的$ ext{mid}$所以还不能卡掉。

    所以它现在还处在半A不A的状态(///▽///)

    //swap
    
    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #define N 4444
    
    using namespace std;
    
    int len,cn;
    char str[N];
    int ans=0;
    int getmid(int mid){
    	int lft=cn,gn=1,lpre=0,rpre=0;
    	for(int i=1;i<=len;i++){
    		if(lft<i-lpre-1 && lft<i-rpre-1)break;
    		if(mid+i>len && mid-i<1)break;
    		if(mid+i<=len && lft>=i-lpre-1 && str[mid+i]==str[mid]){
    			lft-=(i-lpre-1);
    			lpre++;
    			gn++;
    		}
    		if(mid-i>=1 && lft>=i-rpre-1 && str[mid-i]==str[mid]){
    			lft-=(i-rpre-1);
    			rpre++;
    			gn++;
    		}
    	}
    	return gn;
    }
    int main(){
    #ifndef LOCAL
    	freopen("swap.in" ,"r",stdin);
    	freopen("swap.out","w",stdout);
    #endif
    	scanf("%d%d%s",&len,&cn,str+1);
    	for(int i=1;i<=len;i++){
    //		cout<<i<<" "<<getmid(i)<<endl;
    		ans=max(getmid(i),ans);
    	}
    	cout<<ans<<endl;
    }
    

    T2

    好久没有改完题的快感了……

    这个题还是非常可做的qwq

    首先我们先码一个暴力。

    pua!

    $ ext{20%}$算法

    直接暴力即可。

    你可以像这样判断一个数是否是完全平方数。

    bool is_sq(LL val){
    	double sq=sqrt(val);
    	return floor(sq)==ceil(sq);
    }
    

    然后你就被卡精了(滑稽

    发现精度不够……

    bool is_sq(LL val){
    	long double sq=sqrt(val);
    	return floor(sq)==ceil(sq);
    }
    

    好了$1 ext{~}10^{18}$都正确了。

    但是还有一种更有脑子的做法。

    bool is_p2(int va){
        int qva=sqrt(va);
        return qva*qva==va;
    }
    

    另$ ext{20%}$算法

    我们发现有些数很小。

    $a_i leq 1000$

    开桶维护即可。

    • 二合一:
    //square
    
    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #include <vector>
    #include <cmath>
    #define N 333333
    #define sqA 31632
    #define LL long long
    
    using namespace std;
    
    int nn;
    LL arr[N];
    int ans=0;
    
    bool is_sq(LL val){
    	long double sq=sqrt(val);
    //	if(floor(sq)==ceil(sq))cout<<sq<<endl;
    	return floor(sq)==ceil(sq);
    }
    namespace _3{
    	const int T_Size=1111;
    	int tb[T_Size],sqr[T_Size];
    	bool mp[T_Size][T_Size];
    	void prerun(){
    		memset(tb,0,sizeof tb);
    		for(int i=1;i<=1000;i++){
    			sqr[i]=i*i;
    		}
    		for(int i=1;i<=1000;i++){
    			for(int j=1;j<=1000;j++){
    				if(sqr[i]%j==0 && sqr[i]/j<=1000){
    					mp[sqr[i]/j][j]=mp[j][sqr[i]/j]=1;
    				}
    			}
    		}
    	}
    	void work(){
    		prerun();
    		for(int i=1;i<=nn;i++)
    			tb[arr[i]]++;
    		for(int i=1;i<=1000;i++){
    			if(tb[i]==0)continue;
    			for(int j=1;j<=1000;j++){
    				if(mp[i][j]==1){
    //					cout<<i<<" "<<j<<" "<<tb[i]*tb[j]<<endl;
    					if(i!=j)
    						ans+=tb[i]*tb[j];
    					else
    						ans+=tb[i]*(tb[j]-1);
    				}
    			}
    		}
    		cout<<ans/2<<endl;
    	}
    }
    int main(){
    #ifndef LOCAL
    	freopen("square.in" ,"r",stdin);
    	freopen("square.out","w",stdout);
    #endif
    	bool allsm=1;
    	scanf("%d",&nn);
    	for(int i=1;i<=nn;i++){
    		scanf("%lld",arr+i);
    		if(arr[i]>1000)allsm=0;
    	}
    	if(allsm)_3::work();
    	else{
    		for(int i=1;i<=nn;i++){
    			for(int j=i+1;j<=nn;j++){
    				if(is_sq(arr[i]*arr[j])){
    					ans++;
    				}
    			}
    		}
    		cout<<ans<<endl;
    	}
    }
    

    $ ext{70%}$算法

    蒟蒻的思维可能到不了这里??(为什么想了却扔掉了啊?

    我们发现如果某个数有平方因子,那是没有意义的……

    于是求$sqrt{max{a_i}}$内的质数。

    对每个数进行处理,然后排序统计相同的即可。

    如果你开桶($ ext{map}$)好像会被卡常。

    这题还是挺卡常的……

    所以少开long long!

    #include <algorithm>
    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #include <vector>
    #include <cmath>
    #define N 333333
    #define SQ 31633
    
    using namespace std;
    
    int nn,arr[N];
    bool notp[SQ];
    vector <int> pr;
    int ans=0;
    
    void getprime(const int lim){
        notp[1]=1;
        for(int i=2;i<=lim;i++){
            if(!notp[i]){
                pr.push_back(i);
                for(int j=i*2;j<=lim;j+=i){
                    notp[j]=1;
                }
            }
        }
    }
    int main(){
    #ifndef LOCAL
        freopen("square.in" ,"r",stdin);
        freopen("square.out","w",stdout);
    #endif
        int maxn=0;
        cin.sync_with_stdio(false);
        cin>>nn;
        for(int i=1;i<=nn;i++){
            cin>>arr[i];
            maxn=max(maxn,arr[i]);
        }
        getprime(sqrt(maxn)+1);
        for(int i=1;i<=nn;i++){
            int dat=arr[i];
            for(int j=0;j<int(pr.size());j++){
                while(dat%(pr[j]*pr[j])==0)
                    dat/=(pr[j]*pr[j]);
                if(dat==1)break;
            }
    //      cout<<arr[i]<<" "<<dat<<endl;
            arr[i]=dat;
        }
        int val=1;
        sort(arr+1,arr+nn+1);
        for(int i=1;i<=nn;i++){
    //      cout<<arr[i]<<"V"<<val<<endl;
            if(arr[i]==arr[i-1]){
                val++;
            }
            else{
                ans+=val*(val-1)/2;
                val=1;
            }
    //      cout<<arr[i]<<"^"<<val<<endl;
        }
        ans+=val*(val-1)/2;
        cout<<ans<<endl;
    #ifndef LOCAL
    	fclose(stdin);
    	fclose(stdout);
    #endif
    }
    

    $ ext{100%}$算法

    上面的过程非常优秀了,但是由于$sqrt{max{a_i}}$还是太巨了,于是还是只有$70$

    我们就想简化这个过程,

    一个数最多只有一个大于$sqrt[3]{max{a_i}}$的成平方的因子

    那么我们只要想办法解决上面的因子就好了。

    于是先用$sqrt[3]{max{a_i}}$的因子去筛,剩下的判断是否是完全平方数就可以快速处理。

    具体细节见代码:

    #include <algorithm>
    #include <iostream>
    #include <cstdio>
    #include <vector>
    #include <cmath>
    #define SQ3 1211
    #define N 333333
    
    using namespace std;
    
    int nn,arr[N];
    bool notp[SQ3];
    vector <int> pr;
    long long ans=0;
    
    void getprime(const int lim){
        notp[1]=1;
        for(int i=2;i<=lim;i++){
            if(!notp[i]){
                pr.push_back(i);
                for(int j=i*2;j<=lim;j+=i){
                    notp[j]=1;
                }
            }
        }
    }
    bool is_p2(int va){
        int qva=sqrt(va);
        return qva*qva==va;
    }
    int main(){
    #ifndef LOCAL
        freopen("square.in" ,"r",stdin);
        freopen("square.out","w",stdout);
    #endif
        cin.sync_with_stdio(false);
        int maxn=0;
        cin>>nn;
        for(int i=1;i<=nn;i++){
            cin>>arr[i];
            maxn=max(maxn,arr[i]);
        }
        getprime(1100);
        for(int i=1;i<=nn;i++){
            int dat=arr[i];
            for(int j=0;j<int(pr.size());j++){
                while(arr[i]%(pr[j]*pr[j])==0)
                    arr[i]/=pr[j]*pr[j];
                while(dat%pr[j]==0)
                    dat/=pr[j];
            }
    //        cout<<dat<<" "<<arr[i]<<endl;
            if(is_p2(dat))
                arr[i]/=dat;
        }
        sort(arr+1,arr+nn+1);
        int val=1;
        for(int i=1;i<=nn;i++){
            if(arr[i]==arr[i-1])val++;
            else{
                ans+=1ll*val*(val-1)/2;
                val=1;
            }
        }
        ans+=1ll*val*(val-1)/2;
        cout<<ans<<endl;
    #ifndef LOCAL
    	fclose(stdin);
    	fclose(stdout);
    #endif
    }
    

    T3

    好dp题。

    那么就好好写个dp柿子。

    为了找到合法路径我们可以搞一下非法路径。

    于是设$f_i$为以$i$为起点的路径数,记$ways(i,j)$为从$i$到$j$的路径数。

    $$f_i=ways(A,i)-sum limits_{j}^{j ightarrow i} f_j imes ways(i,j)$$

    简单容斥即可。

    #include <algorithm>
    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #define N 111111
    #define D 111
    #define LL long long
    #define aim(k) po[pn+1][(k)]
    
    using namespace std;
    
    const int Mod=1e9+7,
              Phi=Mod-1;
    int dn,pn;
    struct POINT{
        int arr[D];
        int & operator [] (const int id){
            return this->arr[id];
        }
        friend bool operator < (const POINT &a,const POINT &b){
            for(int i=1;i<=dn;i++){
                if(a.arr[i] != b.arr[i])
                    return a.arr[i] < b.arr[i];
            }
            return 1;
        }
    }po[N];
    int fac[N*D],inv[N*D];
    int dp[N];
    LL ans=0;
    
    LL ppow(LL a,LL b){
        a%=Mod;
        b%=Phi;
        LL res=1;
        while(b){
            if(b&1)res=res*a%Mod;
            a=a*a%Mod;
            b>>=1;
        }
        return res;
    }
    void prerun(){
        int lim=10000000;
        fac[0]=inv[0]=1;
        for(int i=1;i<=lim;i++)
            fac[i]=1ll*fac[i-1]*i%Mod;
        inv[lim]=ppow(fac[lim],Mod-2);
        for(int i=lim-1;i>=1;i--){
            inv[i]=1ll*inv[i+1]*(i+1)%Mod;
        }
    }
    LL C(LL n,LL m){
        if(n<m)return 0;
        if(m<0 || n<0) return 0;
        return 1ll*fac[n]*inv[m]%Mod*inv[n-m]%Mod;
    }
    LL getways(int a,int b){
        int sum=0;
        LL dat=1;
        for(int i=1;i<=dn;i++)
            sum+=po[a][i]-po[b][i];
        for(int i=1;i<=dn;i++){
            dat=dat*C(sum,po[a][i]-po[b][i])%Mod;
            sum-=po[a][i]-po[b][i];
        }
        return dat;
    }
    int main(){
    #ifndef LOCAL
        freopen("net.in" ,"r",stdin);
        freopen("net.out","w",stdout);
    #endif
        cin.sync_with_stdio(false);
        prerun();
        cin>>dn>>pn;
        for(int i=1;i<=dn;i++)
            cin>>aim(i);
        for(int i=1;i<=pn;i++){
            for(int j=1;j<=dn;j++){
                cin>>po[i][j];
            }
        }
        ans=getways(pn+1,0);
        sort(po+1,po+pn+1);
    /*    for(int i=1;i<=pn;i++){
            for(int j=1;j<=dn;j++)
                cout<<po[i][j]<<" ";
            cout<<endl;
        }*/
        for(int i=1;i<=pn;i++){
            dp[i]=getways(i,0);
            for(int j=1;j<i;j++){
                dp[i]=(1ll*dp[i]-1ll*dp[j]*getways(i,j)%Mod+Mod)%Mod;
            }
        }
        for(int i=1;i<=pn;i++){
    //        cout<<i<<" "<<dp[i]*getways(pn+1,i)<<endl;
            ans=(ans-1ll*dp[i]*getways(pn+1,i)%Mod+Mod)%Mod;
        }
        cout<<ans<<endl;
    }
    
  • 相关阅读:
    grpc stream剖析
    Pravega架构小结
    Flink之对时间的处理
    一张图说清楚Flink水印和Lateness
    Flink kuduSink开发
    Axsure动态面板下不同状态页面间的交互
    Axsure制作图片动态验证码
    透过用户思维谈程序员的进阶之路
    redis整合Spring之序列化对象与反序列化
    Java基础面试题
  • 原文地址:https://www.cnblogs.com/kalginamiemeng/p/Exam20191109.html
Copyright © 2020-2023  润新知