2018牛客多校3

H    Diff-prime Pairs

1*3 1*5 1*7 1*11.。。。。。

2*3 2*5 2*7 2*11.。。。。。

3*3 3*5 3*7 3*11.。。。。

4*3 4*5 4*7 4*11.。。。。打个素数表 ,用素数筛一遍    

#include<bits/stdc++.h>
using namespace std;
bool a[11111111];
int zs[11111111];
int main(){
    int n;
    a[1]=1;
    int js=0;
    for(long long  i=2;i<=10000000;i++)
    {
        if(a[i]==0)
        {
            zs[js++]=i;
            for(long long j=i*i;j<=10000000;j+=i)
            a[j]=1;
        }
    }
    while(cin>>n)
    {
        long long ans=0;
        for(int i=2;i<=n;i++)
        {
            if(a[i]==0)
            ans++;
        }
        ans=ans*(ans-1);
        for(int i=2;i<=n;i++)
        {
            long long lss=0;
            int j=i;
            int zz=0;
            while(j*zs[zz]<=n)
            {
                lss++;
                zz++;
            }
            if(lss<=1)break;
            ans=ans+lss*(lss-1);
        }
        cout<<ans<<endl;
    }
    return 0;
}

A PACM Team

4维01背包 记录答案

要用2进制来存答案。。。。。

#include<bits/stdc++.h>
using namespace std;
const int N=40;
int dp[N][N][N][N];
long long  path[N][N][N][N];
struct node
{
    int p,a,c,m,w;
}b[N];
int main()
{
    int n;
    while(~scanf("%d",&n))
    {
        memset(dp,0,sizeof(dp));
        memset(path,0,sizeof(path));
        for(int i=0;i<n;i++)
        {
            scanf("%d%d%d%d%d",&b[i].p,&b[i].a,&b[i].c,&b[i].m,&b[i].w);
        }
        int p,a,c,m;
        scanf("%d%d%d%d",&p,&a,&c,&m);
        for(int i=0;i<n;i++)
        {
            for(int j=p;j>=b[i].p;j--)
            {
                for(int x=a;x>=b[i].a;x--)
                {
                    for(int y=c;y>=b[i].c;y--)
                    {
                        for(int z=m;z>=b[i].m;z--)
                        {
                            if(dp[j][x][y][z]<dp[j-b[i].p][x-b[i].a][y-b[i].c][z-b[i].m]+b[i].w)
                            {
                              dp[j][x][y][z]=dp[j-b[i].p][x-b[i].a][y-b[i].c][z-b[i].m]+b[i].w;
                               path[j][x][y][z]=path[j-b[i].p][x-b[i].a][y-b[i].c][z-b[i].m]|(1LL<<i);
                            }
                        }
                    }
                }
            }
        }
        int f=0;
        int ans[N];
        for(int i=0;i<n;i++)
        {
            if(path[p][a][c][m]&(1LL<<i))
            {
 
                ans[f++]=i;
 
            }
        }
        printf("%d\n",f);
        for(int i=0;i<f;i++)
        {
            if(i)printf(" ");
            printf("%d",ans[i]);
        }
        printf("\n");
    }
    return 0;
}

C Shuffle Cards

洗牌按照题意做

可以用平衡树 做 也可以用rope 这个神奇的东西做。。。

学习一波rope

#include<bits/stdc++.h>
#include<ext/rope>
using namespace std;
using namespace __gnu_cxx;
int maxx=1e5+10;
int n,m;
int main(){
	while(cin>>n>>m)
	{
	   rope<int> ro;
	   for(int i=1;i<=n;i++)
	   ro.push_back(i);
	
	int l,r;
	while(m--)
	{
		cin>>l>>r;
		ro.insert(0,ro.substr(l-1,r));
		ro.erase(l+r-1,r);
	}
	for(int i=0;i<n;i++)
	{
		if(i)printf(" ");
		printf("%d",ro[i]);
	}
	printf("\n");
    }
	return 0;
} 

J Distance to Work

求一个圆交多边形面积与多边形面积的比值为(1-(P/Q))

二分一下

#include"bits/stdc++.h"
using namespace std;
const int MX = 222;
 
const double eps = 1e-12;
const double PI = acos( -1.0 ) ;
inline double sqr( double x ){ return x * x ; }
inline int dcmp( double x ){
    if ( fabs(x) < eps ) return 0 ;
    return x > 0? 1 : -1 ;
}
 
struct Point{
    double x , y ;
    Point(){}
    Point( double _x , double _y ): x(_x) , y(_y) {}
    void input() { scanf( "%lf%lf" ,&x ,&y ); }
//    double norm() { return sqrt( sqr(x) + sqr(y) ); }
 
    friend Point operator + ( const Point &a , const Point &b ) { return Point( a.x + b.x , a.y + b.y ) ; }
    friend Point operator - ( const Point &a , const Point &b ) { return Point( a.x - b.x , a.y - b.y ) ; }
    friend Point operator * ( const Point &a , const double &b ) { return Point( a.x * b , a.y * b ) ; }
    friend Point operator * ( const double &a , const Point &b ) { return Point( b.x * a , b.y * a ) ; }
    friend Point operator / ( const Point &a , const double &b ) { return Point( a.x / b , a.y / b ) ; }
    friend bool operator == ( const Point &a , const Point &b ) { return dcmp( a.x - b.x ) == 0 && dcmp( a.y - b.y ) == 0 ; }
 
    bool operator < ( const Point &a )const{
        return ( dcmp( x - a.x ) < 0 ) || ( dcmp( x - a.x ) == 0 && dcmp( y - a.y ) < 0 ) ;
    }
};
typedef Point Vector;
double Dot( Point a , Point b ) { return a.x * b.x + a.y * b.y ; }
double Cross( Point a , Point b ) { return a.x * b.y - a.y * b.x ; }
double Length(Vector A) { return sqrt(Dot(A,A)) ; }
 
int n,m;
Point p[205];
 
int CircleInterLine( Point a, Point b, Point o, double r, Point *p )
{
    Point p1 = a - o ;
    Point d = b - a ;
    double A = Dot( d, d ) ;
    double B = 2 * Dot( d, p1 ) ;
    double C = Dot( p1, p1 ) - sqr(r) ;
 
    double delta = sqr(B) - 4*A*C ;
    if ( dcmp(delta) < 0 ) return 0 ;//相离
    if ( dcmp(delta) == 0 ) { //相切
        double t = -B / (2*A) ; // 0 <= t <= 1说明交点在线段上
        if ( dcmp( t - 1 ) <= 0 && dcmp( t ) >= 0 ) {
            p[0] = a + t * d ;
            return 1 ;
        }
    }
    if ( dcmp(delta) > 0 ) { //相交
        double t1 = ( -B - sqrt(delta) ) / (2*A) ;
        double t2 = ( -B + sqrt(delta) ) / (2*A) ; //0 <= t1, t2 <= 1说明交点在线段上
        int k = 0 ;
        if ( dcmp( t1 - 1 ) <= 0 && dcmp( t1 ) >= 0 )
            p[k++] = a + t1 * d ;
        if ( dcmp( t2 - 1 ) <= 0 && dcmp( t2 ) >= 0 )
            p[k++] = a + t2 * d ;
        return k ;
    }
    return 0;
}
double Triangle_area( Point a, Point b )
{
    return fabs( Cross( a , b ) ) / 2.0  ;
}
double Sector_area( Point a, Point b, double r )
{
    double ang = atan2( a.y , a.x ) - atan2( b.y, b.x  ) ;
    while ( ang <= 0 ) ang += 2.0 * PI ;
    while ( ang > 2.0 * PI ) ang -= 2.0 * PI ;
    ang = min( ang, 2.0*PI - ang ) ;
    return sqr(r) * ang/2.0 ;
}
double calc( Point a , Point b , double r )
{
    Point pi[2] ;
    if ( dcmp( Length(a) - r ) < 0 ) {
        if ( dcmp( Length(b) - r ) < 0 ) {
            return Triangle_area( a, b ) ;
        }
        else {
            CircleInterLine( a, b, Point(0,0), r, pi) ;
            return Sector_area( b, pi[0], r ) + Triangle_area( a, pi[0] ) ;
        }
    }
    else {
        int cnt = CircleInterLine( a, b, Point(0,0), r, pi ) ;
        if ( dcmp( Length(b) - r ) < 0 ) {
            return Sector_area( a, pi[0],r ) + Triangle_area( b, pi[0] ) ;
        }
        else {
            if ( cnt == 2 )
                return Sector_area( a, pi[0],r ) + Sector_area( b, pi[1], r ) + Triangle_area( pi[0], pi[1]) ;
            else
                return Sector_area( a, b, r ) ;
        }
    }
}
double area_CircleAndPolygon( Point *p , int n , Point o , double r )
{
    double res = 0 ;
    p[n] = p[0] ;
    for ( int i = 0 ; i < n ; i++ ) {
        int tmp = dcmp( Cross( p[i] - o , p[i+1] - o ) ) ;
        if ( tmp )
            res += tmp * calc( p[i] - o , p[i+1] - o , r ) ;
    }
    return fabs( res ) ;
}
 
double PolygonArea(Point *p,int n) {
    double area=0;
    for(int i=1; i < n-1; i++)
        area+=Cross(p[i]-p[0],p[i+1]-p[0]);
    return fabs(area/2);
}
 
 
void work(long double &sums, Point o,double P, double Q)
{
 
    long double l = 0, r = 1e4;
    for(int i = 0; i < 100; i++){
        long double mid = (l+r)/2;
        long double ss = area_CircleAndPolygon(p,n,o,mid);
        if((Q-P)*sums > ss*Q) l = mid;
        else r = mid;
    }
    double ans = (l+r)/2;
    printf("%.12f\n",ans);
}
 
int main()
{
    scanf("%d",&n);
    for(int i = 0; i < n; i++){
        scanf("%lf%lf",&p[i].x,&p[i].y);
    }
    long double sums = PolygonArea(p,n);
    scanf("%d",&m);
    for(int i = 1; i <= m; i++){
        double x,y,P,Q;
        scanf("%lf %lf %lf %lf",&x,&y,&P,&Q);
        work(sums,Point(x,y), P,Q);
    }
}

E Sort-String

用map爆内存。

要想到 只有会循环的字符串才能出现重复的按照题意 出现的串

比如 abcdabcdabcd 这样 abcd 重复出现了k次,那么答案就k 0,4,8.。。。。。

那么如果是 abcdabcdabcdz 这样尽管前面有循环,但是最后有一个z ,那么就不循环了,那么答案就是1 0 1 /n  1 0 2。。。这样

所以就要用到kmp中的next数组的定义:

对于一个字符串的长度为len ,   next[i]数组表示将第i个字符去掉,看s[0]~s[i-2] 和 s[1]~s[i-1]这两段里面的重复出现的子串的最大长度(对于第一个子串我从头往后看,对于第二个子串我们从后往前看)。例如 aaaa  next[4]=3;再例如 abababab i=8的话,就是比较 abababa 和bababab这2个子串,根据上方括号的规则,那么就是ababab重复了,那么next[8]=6;

对于这道题,我们要求的是整个串中的最小循环长度,我们发现 上面的8-6=2以及4-3. 刚好是最小循环。

也就是说,对于一个长度为len的字符串来讲,len-next[len]=最小循环长度,那么如果字符串本身不循环,那么可以知道next[len]=0;  那么len-next[len]=len,也就是该字符串自己循环了一次,也就是没有长度小于len的循环子串。且答案符合题意。

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define maxn 1000010
char s[maxn];
int len, Next[maxn];
void makeNext(int tlen) {
    int j = 0, k = -1;
    Next[0] = -1;
    while (j < tlen) {
        if (k == -1 || s[j] == s[k]) {
            Next[++j] = ++k;
        } else {
            k = Next[k];
        }
    }
}
int main()
{
    cin>>s;
    len=strlen(s);
    makeNext(len);
    int x=len-Next[len];
        printf("%d\n",x);
        for(int i = 0; i < x; i++) {
            printf("%d",len/x);
            for(int j = i; j < len; j += x)
                printf(" %d",j);
            printf("\n");
        }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/threeh20/article/details/81251934
今日推荐