/*
测试数据:
0 -0
0 +0
123.123 +00123.12300
100.00 100
.1 0.1
000.000 0
123456789123456789 123456789123456789
1 1
000001000. 1000
*/
#include <stdio.h>
#include <string.h>
void A(char *s)
{
int len = strlen(s);
char *p = s + len - 1;
if (strchr(s, '.'))
while (*p == '0')
*p-- = 0;
if (*p == '.')
*p = 0;
}
int main(void)
{
char *pa, *pb;
char a[100024], b[100024];
while (scanf("%s%s", &a, &b) != EOF)
{
pa = a;
pb = b;
while (*pa == '0')
pa++;
while (*pb == '0')
pb++;
A(pa);
A(pb);
puts(strcmp(pa, pb) ? "NO" : "YES");
}
return 0;
}
Doing Homework again
/*
题目大意:给定一系列任务的截至时间 和无法完成的罚分
解题思路:第N天截至的只能在前N天完成 对于第N天截至的任务 最多只能有N个
超出的必然无法完成 所以对于第N天截至的任务 如果超过N个 那么保留前N大的
后面的必然要罚分 然后从最后一天开始 所有截至日期大于当天的中的罚分最多的任务在当天完成
剩下的继续在下一天继续比较 在开始的时候记录总是罚分sum 用sum减去每次完成的任务的罚分
最后sum即是总是罚分
*/
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
int v[1001];
struct Node
{
int d,s;
}a[1001],b[1001];
bool cmp(Node x,Node y)
{
if(x.d!=y.d)
return x.d<y.d;
else
return x.s>y.s;
}
int main()
{
int t;
cin>>t;
for(int l=1;l<=t;l++)
{
memset(a,0,sizeof(a));
memset(b,0,sizeof(b));
memset(v,0,sizeof(v));
int n;
cin>>n;
for(int i=1;i<=n;i++)
cin>>a[i].d;
int sum=0;
for(int i=1;i<=n;i++)
{
cin>>a[i].s;
sum+=a[i].s;
}
sort(a+1,a+n+1,cmp);
int day=0;
int k=1,kk=1;
for(int i=1;i<=n;i++)
{
if(a[i].d!=day)
{
day=a[i].d;
k=1;
}
else
{
k++;
}
if(k<=a[i].d)
{
b[kk].d=a[i].d;
b[kk++].s=a[i].s;
}
}
sort(b+1,b+kk,cmp);
int p=b[kk-1].d;
for(int i=p;i>=1;i--)
{
int Max=0;
int kkk=0;
for(int j=kk-1;j>=1;j--)
{
if(b[j].d>=i&&!v[j])
{
if(b[j].s>Max)
{
Max=b[j].s;
kkk=j;
}
}
}
sum-=Max;
v[kkk]=1;
}
cout<<sum<<endl;
}
return 0;
}
FATE
/*
二维背包,dp[i][j]表示忍耐度为i,且还可以杀j个怪时能获得的最大经验值
dp[i][j]=max(dp[i][j],dp[i-r[k]][j-1]+e[k]),r[k]为杀死第k种怪掉的忍耐度,
e[k]为第k种怪的经验值
注意方程转移时,我们必须要保证考虑第j个阶段时,我们只放入背包中1个怪,也就是说,
必须做01背包,不能做完全背包
一开始先枚举的就,再枚举k,再从小到大枚举i,这样就变成做完全背包了,
第k类怪可能在同一阶段被放入多次,如果从大到小枚举i就没问题了
*/
#include<stdio.h>
#include<string.h>
#define max(a,b) (a)>(b)?(a):(b)
int dp[101][101];
int v[101],r[101];
int main()
{
int n,m,k,s,i,j,l;
while(scanf("%d%d%d%d",&n,&m,&k,&s)!=EOF)
{
for(i=0;i<k;i++)
scanf("%d%d",&v[i],&r[i]);
memset(dp,0,sizeof(dp));
for(i=0;i<k;i++)
for(j=r[i];j<=m;j++)
for(l=1;l<=s;l++)
dp[j][l]=max(dp[j][l],dp[j-r[i]][l-1]+v[i]);
int flag=0;
for(i=0;i<=m;i++)//遍历满足的经验的最小消耗忍耐度
{
if(flag) break;
for(j=1;j<=s;j++)//怪的数量限制
{
if(dp[i][j]>=n)
{
j=i;flag=1;break;
}
}
}
if(!flag) printf("-1\n");
else printf("%d\n",m-j);
}
return 0;
}
Solitaire
/*
在一个8×8的棋盘中,给定你4个棋子A,再给你4个棋子B,问你在8步之内能不能够从A位置移动到B位置;
规则:棋子能能上下左右移动,同时能跳过相邻的棋子到达相邻棋子的空地方;
这个题要用双向搜索;同时我用一个8维的数组hash来构造一个图;当hash标记为1时表示A到过该点,标记为2时表示B到过该点;
这里要注意就是A,B同时搜索时他们分别最多只能走4步,如果多于4步,那么他们步数之和就可能大于8;
这里还要用到排序,这个很重要,因为4个点是不分形状大小的,那么我们就不会重复走
*/
#include<iostream>
#include<algorithm>
#include<queue>
#include<cstring>
using namespace std;
char visited[8][8][8][8][8][8][8][8];//用来保存四个棋子的状态
int dir[4][2]={{-1,0},{1,0},{0,-1},{0,1}}; //上、下、左、右
struct point {
int x,y;
};
struct node {
struct point p[4]; //一种状态,四个棋子
int step;
};
//给棋排子序,避免同一个状态重复入队列
int cmp(const point &p,const point &q){
if(p.x==q.x)
return p.y<q.y;
return p.x<q.x;
}
//判断是否可以走
int judge(node &s ,int i,int j,int flag){
if( flag==1 ){
if( s.step >=4 )//最多移动4步
return 0;
s.step ++;
}
s.p[i].x += dir[j][0];
s.p[i].y += dir[j][1];
if(s.p[i].x >= 0&&s.p[i].x < 8 &&s.p[i].y >=0&&s.p[i].y<8 ){
int k;
for(k = 0 ; k< 4 ; k++){
if( i!=k ){
if( s.p[i].x== s.p[k].x&& s.p[i].y==s.p[k].y )//判断是否有点,有点的话,就间隔判断
if( flag==1 ) return judge(s ,i ,j, 0);//判断是否跳过相邻的点可以合法走动
else return 0;
}
}
//可以走
if( k>=4 ){
sort(s.p,s.p+4,cmp);
return 1;
}
}
return 0;
}
void bfs(node s1,node s2){
queue<node>Q1,Q2;
node ss;
Q1.push(s1),Q2.push(s2);
visited[s1.p[0].x][s1.p[0].y][s1.p[1].x][s1.p[1].y][s1.p[2].x][s1.p[2].y][s1.p[3].x][s1.p[3].y]='1';
visited[s2.p[0].x][s2.p[0].y][s2.p[1].x][s2.p[1].y][s2.p[2].x][s2.p[2].y][s2.p[3].x][s2.p[3].y]='2';
while((!Q1.empty())||(!Q2.empty())){
if(!Q1.empty()){
for(int i=0;i<4;i++){
//第i个棋子,搜的方向//这是搜走一步的
for(int j=0;j<4;j++){
ss=Q1.front();
if(judge(ss,i,j,1)){
if(visited[ss.p[0].x][ss.p[0].y][ss.p[1].x][ss.p[1].y][ss.p[2].x][ss.p[2].y][ss.p[3].x][ss.p[3].y]=='1')
continue;
//在Q2中已经搜过
if(visited[ss.p[0].x][ss.p[0].y][ss.p[1].x][ss.p[1].y][ss.p[2].x][ss.p[2].y][ss.p[3].x][ss.p[3].y]=='2'){
printf("YES\n");
return ;
}
Q1.push(ss);
visited[ss.p[0].x][ss.p[0].y][ss.p[1].x][ss.p[1].y][ss.p[2].x][ss.p[2].y][ss.p[3].x][ss.p[3].y]='1';//在Q1中搜过的标记为'1';
}
}
}
Q1.pop();//出队列的时候一定要4颗棋子4个方向都试过才能出
}
if(!Q2.empty()){
for(int i=0;i<4;i++){
//第i个棋子,搜的方向//这是搜走一步的
for(int j=0;j<4;j++){
ss=Q2.front();
if(judge(ss,i,j,1)){
if(visited[ss.p[0].x][ss.p[0].y][ss.p[1].x][ss.p[1].y][ss.p[2].x][ss.p[2].y][ss.p[3].x][ss.p[3].y]=='2')
continue;
//在Q1中已经搜过
if(visited[ss.p[0].x][ss.p[0].y][ss.p[1].x][ss.p[1].y][ss.p[2].x][ss.p[2].y][ss.p[3].x][ss.p[3].y]=='1'){
printf("YES\n");
return ;
}
Q2.push(ss);
visited[ss.p[0].x][ss.p[0].y][ss.p[1].x][ss.p[1].y][ss.p[2].x][ss.p[2].y][ss.p[3].x][ss.p[3].y]='2'; //在Q2中搜过的标记为'2';
}
}
}
Q2.pop();
}
}
printf("NO\n");
}
int main(){
int x,y;
while(scanf("%d%d",&x,&y)!=EOF){
node s1,s2;
s1.p[0].x=x-1,s1.p[0].y=y-1;
for(int i=1;i<4;i++){
scanf("%d%d",&x,&y);
s1.p[i].x=x-1,s1.p[i].y=y-1;
}
for(int i=0;i<4;i++){
scanf("%d%d",&x,&y);
s2.p[i].x=x-1,s2.p[i].y=y-1;
}
s1.step=s2.step=0;
sort(s1.p,s1.p+4,cmp);
sort(s2.p,s2.p+4,cmp);
memset(visited,0,sizeof(visited));
bfs(s1,s2);
}
return 0;
}
Building Block
#include<stdio.h>
#include<string.h>
int num[333333];
int set[333333];
int under[333333];
int find(int x)
{
int tmp;
if (x!=set[x])
{
tmp = find(set[x]);
under[x] += under[set[x]];
set[x] = tmp;
}
return set[x];
}
void merge(int a,int b)
{
int fx=find(a);
int fy=find(b);
if(fx!=fy)
{
under[fx]=num[fy];
num[fy]+=num[fx];
set[fx]=fy;
}
}
int main()
{
int n,a,b;
char s[5];
while(scanf("%d",&n)!=EOF)
{
memset(under,0,sizeof(under));
for(int i=0; i<=n; i++)//初始化
{
set[i]=i;
num[i]=1;
}
for(int i=0; i<n; i++)
{
scanf("%s",s);
if(s[0]=='M')
{
scanf("%d%d",&a,&b);
merge(a,b);
}
else
{
scanf("%d",&a);
find(a);
printf("%d\n",under[a]);
}
}
}
return 0;
}
/*
6
M 1 6
C 1
M 2 4
M 2 6
C 3
C 4
*/
Life is a Line
/*
题目大意:求交点的x坐标落于开区间(l,r)的直线对对数.
思路:设直线和x=l交于(l,h1),和x=r交于(r,h2),按照h1降序排序(h1相等的按照h2降序).
得到一个h2数列,求这个h2数列的顺序数(i<j && h2[i]<h2[j]),可以用线段树或树状数组.
*/
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <ctype.h>
#include <math.h>
#include <time.h>
#include <stack>
#include <queue>
#include <map>
#include <set>
#include <vector>
#include <string>
#include <iostream>
#include <algorithm>
using namespace std;
#define ull unsigned __int64
#define ll __int64
//#define ull unsigned long long
//#define ll long long
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define middle (l+r)>>1
#define MOD 1000000007
#define esp (1e-4)
const int INF=0x3F3F3F3F;
const double DINF=10001.00;
//const double pi=acos(-1.0);
const int N=50010;
int n,m;
int sum[N];
double hash[N],L,R;
struct node{
double h1,h2;
bool operator < (const node& p) const {
if(h1==p.h1) return h2 > p.h2;
return h1 > p.h1;
}
}a[N];
int lowbit(int x){return x&(-x);}
void Add(int pos,int c){
while(pos<=m+1) sum[pos]+=c,pos+=lowbit(pos);
}
int Sum(int pos){
int r=0;
while(pos>0) r+=sum[pos],pos-=lowbit(pos);
return r;
}
int bs(double key,int size,double A[]){
int l=0,r=size-1,mid;
while(l<=r){
mid=middle;
if(key==A[mid]) return mid;
else if(key>A[mid]) l=mid+1;
else if(key<A[mid]) r=mid-1;
}
return -1;
}
int main(){
//freopen("1.in","r",stdin);
//freopen("1.out","w",stdout);
int i,j,k,pos,ret;
//int T,cas;scanf("%d",&T);for(cas=1;cas<=T;cas++)
while(~scanf("%d",&n)){
scanf("%lf%lf",&L,&R);
for(i=j=k=0;i<n;i++){
double x1,y1,x2,y2;
scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
if(x1==x2){
if(L<x1 && x1<R) k++;
}else{
a[j].h1=(L-x1)*(y1-y2)/(x1-x2)+y1;
hash[j]=a[j].h2=(R-x1)*(y1-y2)/(x1-x2)+y1;
j++;
}
}
sort(hash,hash+j);
for(i=m=1;i<j;i++) if(hash[i]!=hash[i-1]) hash[m++]=hash[i];
sort(a,a+j);
memset(sum,0,sizeof(sum));
for(i=ret=0;i<j;i++){
pos=bs(a[i].h2,m,hash);
ret+=Sum(pos);
Add(pos+1,1);
}
printf("%d\n",ret+k*j);
}
return 0;
}
Travel
/* THE PROGRAM IS MADE BY PYY */
/*----------------------------------------------------------------------------//
Copyright (c) 2011 panyanyany All rights reserved.
URL : http://acm.hdu.edu.cn/showproblem.php?pid=2433
Name : 2433 Travel
Date : Wednesday, January 25, 2012
Time Stage : 4 hours
Result:
5292805 2012-01-25 14:24:31 Accepted 2433
656MS 324K 2494 B
C++ pyy
Test Data :
Review :
不说了,直接上大牛的解题报告:
http://isomer.me/2011/08/hdu-2433-%E6%9C%80%E7%9F%AD%E8%B7%AF%E9%A2%84%E5%A4%84%E7%90%86/
http://hi.baidu.com/novosbirsk/blog/item/5c26bffbd04d4d6c034f56b7.html
//----------------------------------------------------------------------------*/
#include <cstdio>
#include <CSTRING>
#include <queue>
#include <algorithm>
#include <vector>
using namespace std ;
#define MEM(a, v) memset (a, v, sizeof (a)) // a for address, v for value
#define max(x, y) ((x) > (y) ? (x) : (y))
#define min(x, y) ((x) < (y) ? (x) : (y))
#define INF (0x3f3f3f3f)
#define MAXN 102
struct EDGE {
int u, v ;
} ;
bool used[MAXN], bCnet, bInit ;
int n, m ;
int dist[MAXN], map[MAXN][MAXN], sum_d[MAXN], pre[MAXN][MAXN] ;
EDGE e[30*MAXN] ;
int bfs (int beg)
{
int i, t ;
queue<int> q ;
MEM (used, 0) ;
MEM (dist, 0) ;
used[beg] = 1 ;
// dist[beg] = 0 ;
q.push (beg) ;
while (!q.empty ())
{
t = q.front() ;
q.pop () ;
for (i = 1 ; i <= n ; ++i)
{
if (!used[i] && map[t][i])
{
used[i] = 1 ;
dist[i] = dist[t] + 1 ;
// 只有要第一次 bfs 计算各边的时候才用到
if (bInit)
pre[beg][i] = t ;
q.push (i) ;
}
}
}
int tmpSum = 0 ;
// 从 beg+1 开始 和从 1 开始,效果差不多
for (i = beg + 1 ; i <= n ; ++i)
{
if (!dist[i])
return INF ;
tmpSum += dist[i] ;
}
return tmpSum ;
}
int main ()
{
int i, j ;
int u, v, sum, res ;
while (scanf ("%d%d", &n, &m) != EOF)
{
MEM (map, 0) ;
MEM (pre, 0) ;
for (i = 1 ; i <= m ; ++i)
{
scanf ("%d%d", &u, &v) ;
e[i].u = u ;
e[i].v = v ;
map[u][v] = ++map[v][u] ;
}
sum = 0 ;
bCnet = true ;
bInit = true ;
for (i = 1 ; i <= n ; ++i)
{
sum_d[i] = bfs (i) ;
sum += sum_d[i] ;
// 优化……很显然效果不大
if (sum >= INF)
{
bCnet = false ;
break ;
}
}
bInit = false ;
for (i = 1 ; i <= m ; ++i)
{
u = e[i].u ;
v = e[i].v ;
// map[u][v] 判断有无重边,可以优化300多MS
if (bCnet && map[u][v] == 1)
{
res = 0 ;
for (j = 1 ; j <= n ; ++j)
{
// 最重要的剪枝,否则直接超时
if (pre[j][u] != v && pre[j][v] !=u)
res += sum_d[j] ;
else
{
--map[u][v] ;
--map[v][u] ;
res += bfs (j) ;
++map[u][v] ;
++map[v][u] ;
if (res >= INF)
break ;
}
}
}
else // 一开始漏了这句,一直无限WA,气死了,思维漏洞啊!
res = sum ;
if (res >= INF)
puts ("INF") ;
else
printf ("%d\n", res * 2) ;
}
}
return 0 ;
}
Perfect Squares
/*
先打表,找规律
#include<iostream>
#include<set>
using namespace std;
int main()
{
set<long long>myset;
for(long long i=1;i<20;i++,cout<<endl)
{
myset.clear();
for(long long j=0;j<1000000;j++)
myset.insert(j*j%(1<<i));
cout<<i<<' '<<myset.size();
}
return 0;
}
f(i)=4*f(i-2)-5 通项 f(i)=(2^(n-1)+5)/3 i为奇数
f(i)=4*f(i-2)-4 f(i)=(2^(n-1)+4)/3 i为偶数
即 f(i)=(2^(n-1)+4+n%1)/3
若b%c=1,则a/b%c=a%c=d,证明如下:
b=c*k1+1 a=b*(c*k2+d)=(c*k1+1)*(c*k2+d)=c*(k1*k2+k1*d+k2)+d=c*k3+d
因此a%c=d=a/b%c
求解f(i)%mod,a/b%c=(a*k)/(b*k)%c=a*k%c,(b*k%c=1)
即求任一k使b*k%c=1, 即b*k=c*k'+1,设x=k,y=-k’,则x*b+y*c=1,extgcd或者打表求一个x即可
#include<iostream>
using namespace std;
int extgcd(int &x,int &y,int a,int b)
{
if(b==0){x=1,y=0;return a;}
int d=extgcd(x,y,b,a%b);
int t=x;x=y;y=t-a/b*y;
return d;
}
int main()
{
int x,y;
extgcd(x,y,3,10007);
cout<<x<<endl;
}
#include<iostream>
using namespace std;
int main()
{
for(int i=1;i<1000000;i++)
if(i*3%10007==1)
{
cout<<i<<endl;break;
}
}
所以f(i)=(2^(n-1)+4+n%1)*3336%10007.
*/
#include<iostream>
using namespace std;
typedef long long ll;
const ll mod=10007;
ll pow(ll n)
{
ll ans=1,base=2;
while(n)
{
if(n&1) ans=ans*base%mod;
base=base*base%mod,n>>=1;
}
return ans;
}
int main()
{
ll t,n,cas=1;
cin>>t;
while(t--)
{
cin>>n;
cout<<"Case #"<<cas++<<": "<<3336*(pow(n-1)+4+(n&1))%mod<<endl;
}
return 0;
}