技巧

对拍

正确的程序(daan)

#include <iostream>  
using namespace std;    

int main()  
{   
    int a,b;    
    cin >> a >> b;   
    cout << a+b << endl;   
    return 0;    
} 

需要测试的程序(yuan)

#include <stdio.h>  

int main()   
{  
    int a, b;  
    scanf("%d %d",&a, &b);  
    printf("%d\n", a+b);  
    return 0;  
} 

数据生成(data)

#include <iostream>   
#include <cstdio>  
#include <cstdlib>  
#include <cstring>  
#include <ctime>  
#include <fstream>  
#include <algorithm>  
#include <windows.h>  
using namespace std;  
int main()  
{  
    srand(time(0));     
    int a,b;  
    a=rand()%100+1,b=rand()%100+1;  
    printf("%d %d\n",a,b);   
    return 0;  
} 

对拍

#include<iostream>  
#include<windows.h>  
using namespace std;  
int main()  
{   
    while(1)  
    {  
        system("data.exe > data.txt");  
        system("daan.exe < data.txt > daan.txt");  
         system("yuan.exe < data.txt > yuan.txt");  
        if(system("fc yuan.txt daan.txt"))   break;  
    }  
    return 0;  
}  

全部生成的exe文件放在一起,运行duipai.exe

模拟退火

P1337 [JSOI2004] 平衡点 / 吊打XXX(交了21次才调对)

t越大越准,jiang越大越准,run()跑的次数越多越准
建议t不要大于1e9,run()五次左右,jiang能不T的话最好0.999

#include<bits/stdc++.h>
#define for1(i,a,b) for(int i = a;i<=b;i++)
#define ll long long
#define mp(a,b) make_pair(a,b)
using namespace std;
struct node{
	int x;
	int y;
	int w;
}a[500005];
int n,m;
double ansx,ansy;
double ans=1e18+7,t;
const double jiang=0.994;//降温系数

double cl(double x,double y)//这个我也看不懂,简单来说就是计算答案 
{
	double sum=0;
	for(int i=1;i<=n;i++)
	{
		double dx=x-a[i].x;
		double dy=y-a[i].y;
		sum+=(sqrt(dx*dx+dy*dy))*a[i].w;
		//物重一定,绳子越短,重物越低,势能越小 
		//势能又与物重成正比 
	}
	return sum;//在(nowx,nowy)处的总势能 
}

void run()
{
	double jx=ansx;
	double jy=ansy;
	t=1e9;
	while(t>1e-15)
	{
		
		double xinx=ansx+(rand()*2-RAND_MAX)*t;
		double xiny=ansy+(rand()*2-RAND_MAX)*t;
		
		double xinans=cl(xinx,xiny);
		double de=xinans-ans;
		if(de<0)//更优
		{
			
		    jx=xinx;
			jy=xiny;//就接受
			ansx=jx;
			ansy=jy;
			ans=xinans;
		 } 
		 else if(exp(-de/t)*RAND_MAX>rand())//看看是否有概率接受 
		 {
		 	jx=xinx;
			jy=xiny;
		 }
		 t*=jiang;//降温 
	}
	
}
void sa()
{
	run();
	run();
	run();
	run();
}
int main() {
	cin>>n;
	for1(i,1,n)
		scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].w);
	ansx/=n;//以平均数作为初始答案 
    ansy/=n;
    ans=cl(ansx,ansy);
	sa();
	printf("%.3lf %.3lf",ansx,ansy);
	return 0;
}

离散化

https://www.cnblogs.com/yyx525jia/p/16735119.html

珂朵莉树(ODT)
本质上其实就是一个去重的暴力
可以学习到一些炫酷的代码打法

#include<bits/stdc++.h>
#define s_it set<node>::iterator	//s_it = set_iterator
#define for1(i,a,b) for(int i=a;i<=b;i++)
#define mp(a,b) make_pair(a,b) 
using namespace std; 
typedef long long type;
const int MOD7 = 1e9 + 7;
const int MOD9 = 1e9 + 9;
const int imax_n = 1e5 + 7;
struct node
{
	int l;
	int r;
	mutable type val;
	node(int a,int b = 0, type c = 0);
};
node::node(int a,int b, type c)
{
 l = a;
 r = b;
 val = c;
}


bool operator <(const node &a,const node &b)
{
	return a.l<b.l;
}
set<node> s;

s_it split(int pos)//找到一个区间里含有pos这个位置的点 
{
	s_it it = s.lower_bound(node(pos));//默认参数r与cal为0 
	if (it != s.end() && it->l == pos)//如果左端点就是或者找不到 
	return it;
	//否则就要分裂成两个区间 
	--it;
	unsigned int l = it->l, r = it->r;
	type val = it->val;
	s.erase(it);
	s.insert(node(l, pos - 1, val));
	return s.insert(node(pos, r, val)).first;//first 返回地址 secon的返回是否被插入成功 
}

void assign(int l,int r, type val)//把l到r全部赋值成val的操作 
{
	s_it itr = split(r + 1), itl = split(l);//访问区间l-r 
	//必须先声明it2,因为it1在前的话地址可能会失效 
 	s.erase(itl, itr); 
 	s.insert(node(l, r, val));//l到r的整个区间全部变成一个点
    return;
}

void add(int l, int r, type val)//区间加 
{
    s_it itr = split(r+1),itl = split(l);
    for (; itl != itr; ++itl) //访问区间l到r标准套路 
        itl->val += val;
}

type ranks(int l, int r, int k)//区间第k小 
{
    vector<pair<type, int> > ji;
    s_it itr = split(r+1),itl = split(l);
    ji.clear();
    pair<type,int> jl;
    for (; itl != itr; ++itl)
    {
    	jl=mp(itl->val, (itl->r)-(itl->l)+1);//权值与区间长度
    	ji.push_back(jl); 
	}
    sort(ji.begin(), ji.end());//按权值排序
	vector<pair<type,int> >::iterator it=ji.begin();
    for (;it!=ji.end();++it)
    {
        k -= it->second;
        if (k <= 0) 
            return it->first;
    }
}

type pown(type a, type b, type mod)//快速幂 1
{
    type res = 1;
    type ans = a % mod;
    while (b)
    {
        if (b%2==1) 
            res = res * ans % mod;
        ans = ans * ans % mod;
        b/=2;
    }
    return res;
}

type sum(int l, int r, int ex, int mod)//区间次幂和  2
{
    s_it itl = split(l),itr = split(r+1);
    type res = 0;
    for (; itl != itr; ++itl)
        res = (res + (type)(itl->r - itl->l + 1) 
		*pown(itl->val, type(ex), type(mod))) % mod;
		//本质上就是用快速幂把区间相同的数算出来,然后再直接*区间长度 
    return res;
}
int n, m;
type seed, vmax;
type rd()
{
    type ret = seed;
    seed = (seed * 7 + 13) % MOD7;
    return ret;
}
type a[imax_n];

int main()
{
    cin>>n>>m>>seed>>vmax;
    for1(i,1,n)
    {
        a[i] = (rd() % vmax) + 1;
        s.insert(node(i,i,a[i]));
    }
    s.insert(node(n+1, n+1, 0));
    int lines = 0;
    for1(i,1,m)
    {
        int op = int(rd() % 4) + 1;
        int l = int(rd() % n) + 1;
        int r = int(rd() % n) + 1;
        if (l > r)
            swap(l,r);
        int x, y;
        if (op == 3)
            x = int(rd() % (r-l+1)) + 1;
        else
            x = int(rd() % vmax) +1;
        if (op == 4)
            y = int(rd() % vmax) + 1;
        if (op == 1)
            add(l, r, type(x));
        else if (op == 2)
            assign(l, r, type(x));
        else if (op == 3)
            cout<<ranks(l,r,x)<<endl;
        else
            cout<<sum(l,r,x,y)<<endl;
    }
    return 0;
}
posted @ 2022-09-08 22:18  yyx525jia  阅读(20)  评论(0)    收藏  举报